Могу ли я удалить CancellationTokenSource до отмены задачи?

Могу ли я избавиться от CancellationTokenSource до того, как Task будет отменено? Если нет, то почему?

Код 1 (из задачи Отмена. Я внес небольшие изменения для упрощения) кажется, рекомендуется подождать Task перед удалением CancellationTokenSource. Если это так, то метод Dispose класса, содержащего CancellationTokenSource, будет сложнее, чем я надеюсь.

На моем ПК код 2 тоже работает нормально. Могу ли я использовать этот шаблон вместо этого?

Код 1: Утилизировать ПОСЛЕ завершения отмены

    [STAThread]
    private static void Main() {
        var tokenSource2 = new CancellationTokenSource();
        var task = DoAsync(tokenSource2.Token);
        tokenSource2.Cancel();
        tokenSource2 = null;

        try {
            task.Wait();
        }
        catch (AggregateException e) {
            foreach (var v in e.InnerExceptions)
                Console.WriteLine(e.Message + " " + v.Message);
        }
        finally {
            tokenSource2.Dispose();
        }

        Console.ReadKey();
    }

    private static async Task DoAsync(CancellationToken token) {
        while (true) {
            await Task.Delay(10000).ConfigureAwait(true);
            token.ThrowIfCancellationRequested();
        }
    }

Код 2: утилизировать до завершения отмены

    [STAThread]
    private static void Main() {
        var tokenSource2 = new CancellationTokenSource();
        var task = DoAsync(tokenSource2.Token);
        tokenSource2.Cancel();
        tokenSource2.Dispose();

        try {
            task.Wait();
        }
        catch (AggregateException e) {
            foreach (var v in e.InnerExceptions)
                Console.WriteLine(e.Message + " " + v.Message);
        }
        finally {
            //// tokenSource2.Dispose();
        }

        Console.ReadKey();
    }

    private static async Task DoAsync(CancellationToken token) {
        while (true) {
            await Task.Delay(10000).ConfigureAwait(true);
            token.ThrowIfCancellationRequested();
        }
    }

РЕДАКТИРОВАТЬ: мой случай

На самом деле мне интересно, нужно ли мне Wait для отмены задачи в методе Dispose.

    public class Class1 : IDisposable {
        //// tokenSource for calculationTask
        private CancellationTokenSource tokenSource;

        //// background calculation task
        private Task calculationTask;

        public void Dispose() {
            tokenSource?.Cancel();
            //// calculationTask.Wait(); Should I wait for task completion?
            tokenSource?.Dispose();
            tokenSource = null;

            calculationTask = null;
        }
    }



Ответы (1)


Я не совсем понимаю, что вы пытаетесь сделать, однако давайте посмотрим на факты.

Удаление источника токена не влияет на токен, однако просто не имеет смысла удалять его до завершения задачи. Кроме того, всегда используйте оператор using, если он доступен.

Кроме того, вы можете использовать асинхронные основные методы, в С# 7.1 или более поздней версии, я полагаю. просто измените расширенный параметр в настройках сборки.

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

// use async all the way down
static async Task Main(string[] args)
{
   // using using using
   using (var tokenSource2 = new CancellationTokenSource())
   {
      try
      { 
         var task = DoAsync(tokenSource2.Token);

         // test cancel
         tokenSource2.Cancel();

         // await anything you need.
         await Task.WhenAll(task);  
      }
      // catch CanceledException
      catch (OperationCanceledException)
      {
         Console.WriteLine("Canceled");
      }
      // notice we get normal exceptions and not aggregates 
      catch (Exception e)
      {
         Console.WriteLine(e.Message);
      }    
   }   
   Console.ReadKey();
}

private static async Task DoAsync(CancellationToken token)
{
   // pass your toke in to anything that needs it
   await Task.Delay(10000,token).ConfigureAwait(true);
   token.ThrowIfCancellationRequested(); 
}
person TheGeneral    schedule 19.11.2018
comment
Спасибо @TheGeneral за ваш ответ! Мой вопрос, возможно, был двусмысленным. На самом деле мне интересно, должен ли я Wait для отмены задачи в методе Dispose. Пожалуйста, проверьте отредактированную часть. - person terasato; 19.11.2018