2017-10-13 91 views
3

.NET中的TPL新手。试图了解CancellationToken以及它们如何通知取消正在执行的任务。下面的代码只传递一个被取消的任务,因为相同的令牌传递给两个任务。我的假设是如果超时发生在第一个任务上并且它执行ctx.Cancel()我需要一些帮助来理解为什么我只看到一个例外,因为这两个任务都应该被取消。我错过了什么,以及如何确保这两个任务都取消并且不占用内存资源。CancellationToken不取消所有任务

static void Main(string[] args) 
    { 
     Console.WriteLine("Starting application"); 
     var ctx = new CancellationTokenSource(); 
     var token = ctx.Token; 
     try 
     { 
      var task1 = new Program().Run("task1", token); 
      var task2 = new Program().Run("task2", token); 

      if (!task1.Wait(1000)) 
       ctx.Cancel(); 

      task2.Wait(); 
     } 
     catch (AggregateException ex) 
     { 
      Console.WriteLine("Aggregate Exception occurred"); 
      foreach (var e in ex.InnerExceptions) 
      { 
       Console.WriteLine(e.Message); 
      } 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine($"Main Exception: {e.Message}"); 
     } 
     finally 
     { 
      Console.WriteLine("Finish Application"); 
      ctx.Dispose(); 
     } 
    } 

    private async Task Run(string name, CancellationToken token) 
    { 
     while(true) 
     { 
      if (token.IsCancellationRequested) 
      { 
       Console.WriteLine("Task Cancelled"); 
       token.ThrowIfCancellationRequested(); 
      } 
      Console.WriteLine($"Executing {name} ..."); 
      await Task.Delay(250, token);     
     } 
    } 

只抛出一个异常,其他任务发生了什么?另外,Console.WriteLine("Task Cancelled")从未得到执行。

输出:

Starting application 
Executing task1 ... 
Executing task2 ... 
Executing task2 ... 
Executing task1 ... 
Executing task1 ... 
Executing task2 ... 
Executing task2 ... 
Executing task1 ... 
Aggregate Exception occurred 
A task was canceled. 
Finish Application 

回答

3

两件事情:

  1. 你应该叫ex.Flatten().InnerExceptions看看this参考
  2. Task.Delaythrowing,而不是你的取消逻辑。尝试将其包装在try catch中进行记录。或者,您可能无法通过tokenTask.Delay
+0

如果您没有将CancellationToken传递给Task.Delay,那么您有点错过了取消CancellationToken。 –

+0

@JoeWhite,我想你有一点,建议是为了确保使用取消处理逻辑。 – mrtig

+0

@mrtig这很有帮助,但这是否意味着一旦发布取消令牌,所有任务都会被正确终止? –

相关问题