2017-10-13 78 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這很有幫助,但這是否意味着一旦發佈取消令牌,所有任務都會被正確終止? –