Я играю с этими задачами Windows 8 WinRT и пытаюсь отменить задачу, используя метод, описанный ниже, и в какой-то момент это работает. Метод CancelNotification ДОЛЖЕН вызываться, что заставляет вас думать, что задача была отменена, но в фоновом режиме задача продолжает выполняться, затем после ее завершения состояние задачи всегда завершается и никогда не отменяется. Есть ли способ полностью остановить задачу, когда она отменена?
private async void TryTask()
{
CancellationTokenSource source = new CancellationTokenSource();
source.Token.Register(CancelNotification);
source.CancelAfter(TimeSpan.FromSeconds(1));
var task = Task<int>.Factory.StartNew(() => slowFunc(1, 2), source.Token);
await task;
if (task.IsCompleted)
{
MessageDialog md = new MessageDialog(task.Result.ToString());
await md.ShowAsync();
}
else
{
MessageDialog md = new MessageDialog("Uncompleted");
await md.ShowAsync();
}
}
private int slowFunc(int a, int b)
{
string someString = string.Empty;
for (int i = 0; i < 200000; i++)
{
someString += "a";
}
return a + b;
}
private void CancelNotification()
{
}
Ответы:
Читайте об отмене (которая была введена в .NET 4.0 и с тех пор практически не изменилась) и асинхронном шаблоне на основе задач , который содержит рекомендации по использованию
CancellationToken
сasync
методами.Подводя итог, вы передаете
CancellationToken
в каждый метод, который поддерживает отмену, и этот метод должен периодически проверять его.источник
CancellationToken
имеет все возможности, необходимые для взаимодействия с пользовательскими системами отмены, но ничто не может отменить невозможный метод.Wait
илиResult
вasync
методах; Вы должны всегда использоватьawait
вместо этого, который правильно разворачивает исключение.CancellationToken.IsCancellationRequested
и вместо этого предлагает исключение?Или, чтобы избежать изменений
slowFunc
(например, у вас нет доступа к исходному коду):Вы также можете использовать хорошие методы расширения из https://github.com/StephenCleary/AsyncEx, и они будут выглядеть так просто:
источник
ConfigureAwait
иначе вы можете пострадать в приложениях пользовательского интерфейса.using
.Один случай, который не был рассмотрен, это как обрабатывать отмену внутри асинхронного метода. Возьмем, к примеру, простой случай, когда вам нужно загрузить некоторые данные в сервис, заставить их вычислить что-то, а затем вернуть некоторые результаты.
Если вы хотите поддержать отмену, тогда самым простым способом будет передать токен и проверить, был ли он отменен между каждым вызовом асинхронного метода (или с использованием ContinueWith). Если они очень длинные, хотя вы можете подождать, чтобы отменить их. Я создал небольшой вспомогательный метод, который вместо этого завершился неудачей, как только его отменили.
Поэтому, чтобы использовать его, просто добавьте
.WaitOrCancel(token)
к любому асинхронному вызову:Обратите внимание, что это не остановит задачу, которую вы ждали, и продолжит работу. Вам нужно использовать другой механизм , чтобы остановить его, например,
CancelAsync
вызов в примере, или еще лучше пройти в то же самоеCancellationToken
кTask
так , что он может обрабатывать отмены в конце концов. Попытка прервать поток не рекомендуется .источник
UploadDataAsync
может продолжаться в фоновом режиме, но после ее завершения вызов не будет выполнен,CalculateAsync
поскольку эта часть уже перестала ждать). Это может быть или не быть проблематичным для вас, особенно если вы хотите повторить операцию. ПрохождениеCancellationToken
полностью вниз является предпочтительным вариантом, когда это возможно.Я просто хочу добавить к уже принятому ответу. Я застрял на этом, но я шел другим путем обработки полного события. Вместо запуска await я добавляю завершенный обработчик к задаче.
Где обработчик событий выглядит так
С этим маршрутом вся обработка уже сделана для вас, когда задача отменяется, она просто запускает обработчик события, и вы можете видеть, была ли она отменена там.
источник