kzen.dev
  • Вопросы
  • Метки
  • Пользователи
Оповещения
Вознаграждения
Регистрация
После регистрации, сможете получать уведомления об ответах и комментариях на Ваши вопросы.
Вход
Если у Вас уже есть аккаунт, войдите чтобы проверить новые уведомления.
Тут будут вознаграждения за добавленные вопросы, ответы и комментарий.
Дополнительно
Источник
Редактировать
 Carlo
Carlo
Вопрос

Как отменить задачу в await?

Я'играю с этими задачами Windows 8 WinRT, и я'пытаюсь отменить задачу, используя метод ниже, и это работает до некоторой степени. Метод CancelNotification DOES вызывается, что заставляет вас думать, что задача была отменена, но в фоновом режиме задача продолжает выполняться, а после ее завершения статус задачи всегда остается завершенным и никогда не отменяется. Есть ли способ полностью остановить задачу, когда она отменяется?

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()
{
}
147 2012-04-13T01:53:19+00:00 4
 Carlo
Carlo
Редактировал вопрос 13-го апреля 2012 в 2:41
Программирование
c#
task-parallel-library
.net-4.5
Решение / Ответ
Stephen Cleary
Stephen Cleary
13-го апреля 2012 в 2:43
2012-04-13T02:43:33+00:00
Дополнительно
Источник
Редактировать
#15927416

Ознакомьтесь с Cancellation (который был введен в .NET 4.0 и практически не изменился с тех пор) и Task-Based Asynchronous Pattern, который содержит рекомендации по использованию CancellationToken с методами async.

Вкратце, вы передаете CancellationToken в каждый метод, который поддерживает отмену, и этот метод должен периодически проверять его.

private async Task TryTask()
{
  CancellationTokenSource source = new CancellationTokenSource();
  source.CancelAfter(TimeSpan.FromSeconds(1));
  Task<int> task = Task.Run(() => slowFunc(1, 2, source.Token), source.Token);

  // (A canceled task will raise an exception when awaited).
  await task;
}

private int slowFunc(int a, int b, CancellationToken cancellationToken)
{
  string someString = string.Empty;
  for (int i = 0; i < 200000; i++)
  {
    someString += "a";
    if (i % 1000 == 0)
      cancellationToken.ThrowIfCancellationRequested();
  }

  return a + b;
}
216
0
 sonatique
sonatique
9-го октября 2015 в 1:49
2015-10-09T13:49:23+00:00
Дополнительно
Источник
Редактировать
#15927491

Или для того, чтобы избежать модификации slowFunc (например, у вас нет доступа к исходному коду):

var source = new CancellationTokenSource(); //original code
source.Token.Register(CancelNotification); //original code
source.CancelAfter(TimeSpan.FromSeconds(1)); //original code
var completionSource = new TaskCompletionSource<object>(); //New code
source.Token.Register(() => completionSource.TrySetCanceled()); //New code
var task = Task<int>.Factory.StartNew(() => slowFunc(1, 2), source.Token); //original code

//original code: await task;  
await Task.WhenAny(task, completionSource.Task); //New code

Вы также можете использовать красивые методы расширения из https://github.com/StephenCleary/AsyncEx, и тогда все будет выглядеть просто:

await Task.WhenAny(task, source.Token.AsTask());
 sonatique
sonatique
Редактировал ответ 14-го марта 2018 в 6:16
35
0
 kjbartel
kjbartel
20-го ноября 2018 в 1:01
2018-11-20T13:01:29+00:00
Дополнительно
Источник
Редактировать
#15927511

Один случай, который до сих пор'т был покрыт как обработка отмены внутри асинхронного метода. Возьмем для примера простой случай, когда вам нужно, чтобы загрузить некоторые данные в службу заставить его что-то подсчитать и затем вернуть результаты.

public async Task<Results> ProcessDataAsync(MyData data)
{
    var client = await GetClientAsync();
    await client.UploadDataAsync(data);
    await client.CalculateAsync();
    return await client.GetResultsAsync();
}

Если вы хотите поддерживать отмену, то проще всего будет передать маркер и проверить, если он был отменен между каждым вызовом асинхронного метода (или через ContinueWith). Если они очень длительные звонки, хотя вы могли бы ждать некоторое время, чтобы отменить. Я создал небольшой вспомогательный метод, а не плохо, как только отменили.

public static class TaskExtensions
{
    public static async Task<T> WaitOrCancel<T>(this Task<T> task, CancellationToken token)
    {
        token.ThrowIfCancellationRequested();
        await Task.WhenAny(task, token.WhenCanceled());
        token.ThrowIfCancellationRequested();

        return await task;
    }

    public static Task WhenCanceled(this CancellationToken cancellationToken)
    {
        var tcs = new TaskCompletionSource<bool>();
        cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).SetResult(true), tcs);
        return tcs.Task;
    }
}

Поэтому использовать его тогда просто добавьте `.WaitOrCancel(маркер) для любого асинхронного вызова:

public async Task<Results> ProcessDataAsync(MyData data, CancellationToken token)
{
    Client client;
    try
    {
        client = await GetClientAsync().WaitOrCancel(token);
        await client.UploadDataAsync(data).WaitOrCancel(token);
        await client.CalculateAsync().WaitOrCancel(token);
        return await client.GetResultsAsync().WaitOrCancel(token);
    }
    catch (OperationCanceledException)
    {
        if (client != null)
            await client.CancelAsync();
        throw;
    }
}

Обратите внимание, что это не остановит задания, вы ждали и она будет продолжать работать. Вы'll необходимо использовать другой механизм, чтобы остановить его, такие как CancelAsync позвонить в Примере, а еще лучше сдать в той жеCancellationTokenкзадача`, так что он может обрабатывать отмену в конце концов. Пытаясь прервать поток разве'т рекомендуется.

 kjbartel
kjbartel
Редактировал ответ 6-го августа 2019 в 7:08
11
0
 Smeegs
Smeegs
2-го августа 2012 в 1:22
2012-08-02T01:22:15+00:00
Дополнительно
Источник
Редактировать
#15927486

Я просто хочу добавить к уже принятому ответу. Я застрял на этом, но я пошел другим путем в обработке завершенного события. Вместо того чтобы запускать await, я добавляю обработчик завершения к задаче.

Comments.AsAsyncAction().Completed += new AsyncActionCompletedHandler(CommentLoadComplete);

Где обработчик события выглядит следующим образом

private void CommentLoadComplete(IAsyncAction sender, AsyncStatus status )
{
    if (status == AsyncStatus.Canceled)
    {
        return;
    }
    CommentsItemsControl.ItemsSource = Comments.Result;
    CommentScrollViewer.ScrollToVerticalOffset(0);
    CommentScrollViewer.Visibility = Visibility.Visible;
    CommentProgressRing.Visibility = Visibility.Collapsed;
}

С этим маршрутом вся обработка уже сделана за вас, когда задача отменяется, она просто запускает обработчик события, и вы можете увидеть, была ли она отменена там.

 EluciusFTW
EluciusFTW
Редактировал ответ 19-го декабря 2017 в 4:16
6
0
Похожие сообщества 16
DotNetRuChat
DotNetRuChat
6 630 пользователей
Чат русскоязычного .NET сообщества http://dotnet.ru/ Правила: https://t.me/DotNetRuChat/704399 Вам могут быть интересны: @dotnetchat, @cilchat, @fsharp_chat, @pro_net, @AvaloniaRU, @xamarin_russia, @DotNetRuJobs, @uwp_ru Флуд в @dotnettalks
Открыть telegram
Вакансии .NET
Вакансии .NET
3 530 пользователей
Правила: https://t.me/DotNetRuJobs/123 Канал с вакансиями - https://t.me/DotNetRuJobsFeed Вам могут быть интересны: @dotnetruchat, @cilchat, @fsharp_chat, @pro_net, @AvaloniaRU, @xamarin_russia Флуд в @dotnettalks
Открыть telegram
Microsoft Stack Jobs
Microsoft Stack Jobs
2 408 пользователей
Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks
Открыть telegram
С#
С#
2 330 пользователей
Стараемся не флудить. Пишем по делу. Правила: https://t.me/professorweb/430450 Для флуда @svoboda_obsh
Открыть telegram
pro.net
pro.net
1 820 пользователей
Обсуждение .NET и всего, что с ним связано. Правила: не флудить не по теме, уважать ваших коллег и никакой рекламы (объявления о вакансиях можно согласовать с @AlexFails). https://t.me/pro_net/34653 Флудилка: @dotnettalks
Открыть telegram
CODE BLOG / C#
CODE BLOG / C#
1 763 пользователей
Чат для .NET разработчиков и C# программистов. По всем вопросам: @shwanoff Youtube-канал: https://youtube.com/codeblog Основной канал: @codeblog Вконтакте: https://vk.com/codeblog Правила: https://t.me/codeblog_csharp/246972 Вакансии по тегу #work
Открыть telegram
Добавить вопрос
Категории
Все
Технологий
Культура / Отдых
Жизнь / Искусство
Наука
Профессии
Бизнес
Пользователи
Все
Новые
Популярные
1
Денис Васьков
Зарегистрирован 15 часов назад
2
Dima Patrushev
Зарегистрирован 2 дня назад
3
sirojidddin otaboyev
Зарегистрирован 1 неделю назад
4
Елена Гайдамамакинат
Зарегистрирован 1 неделю назад
5
Иван Степанюк
Зарегистрирован 1 неделю назад
ID
JA
KO
RO
RU
© kzen.dev 2023
Источник
stackoverflow.com
под лицензией cc by-sa 3.0 с атрибуцией