Могу ли я утилизировать CancellationTokenSource до отмены задачи? - PullRequest
0 голосов
/ 19 ноября 2018

могу ли я распоряжаться CancellationTokenSource до отмены Task?Если нет, то почему?

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

На моем компьютере Code 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 Ответ

0 голосов
/ 19 ноября 2018

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

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

Кроме того, вы можете использовать асинхронные основные методы, в C # 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(); 
}
...