3

我已經得到了下面的例子:如何使用ContinueWith處理任務取消?

public void Run() 
{ 
    var ctc = new CancellationTokenSource(); 

    try 
    { 
     DoAsync(ctc).Wait(); 

     Console.WriteLine("Done"); 
    } 
    catch (AggregateException exception) 
    { 
     Console.WriteLine("Inside try-catch block"); 
     Console.WriteLine(); 
     Console.WriteLine(exception); 

     exception.Handle(ex => 
     { 
      Console.WriteLine(ex.Message); 
      return true; 
     }); 
    } 
} 

private async Task DoAsync(CancellationTokenSource ctc) 
{ 
    Console.WriteLine("DoAsync started"); 

    await Task.Run(() => 
       Console.WriteLine("DoAsync Run"), 
       ctc.Token 
      ) 
      .ContinueWith(antecedent => 
       Console.WriteLine("DoAsync Run cancelled"), 
       TaskContinuationOptions.OnlyOnCanceled 
      ); 

    Console.WriteLine("DoAsync finished"); 
} 

我已經創建了一個做一些異步工作,並可以在任何時候取消的方法(DoAsync)。

正如你可以看到Task.Run獲取取消令牌。爲此,我使用continuationOptions = TaskContinuationOptions.OnlyOnCanceled創建了延續任務。

因此,我期望繼續任務僅在請求取消時和在其他情況下被忽略。

但通過ContinueWith回我執行任務拋出時,其先行任務不被取消異常:

DoAsync started 
DoAsync Run 

Inside try-catch block 
System.AggregateException... 

A task was canceled. 

我可以通過添加另一個ContinueWith在下面的例子中解決這個問題:

await Task.Run(() => 
     Console.WriteLine("DoAsync Run"), 
     ctc.Token 
    ) 
    .ContinueWith(antecedent => 
     Console.WriteLine("DoAsync Run cancelled"), 
     TaskContinuationOptions.OnlyOnCanceled 
    ) 
    .ContinueWith(antecedent => { }); 

而這段代碼不會拋出任何異常。

但是我能否處理取消使用單號ContinueWith正確嗎?

+0

你有沒有試過只傳遞令牌,而不是令牌源? – Fildor

+1

@Fildor,我同意我應該傳遞令牌而不是令牌源。但是它如何解決我的問題? –

+0

它可能不會。這就是爲什麼它只是一個評論。但也許它會減少副作用。我沒有看到明顯的原因,爲什麼你的代碼不能按預期工作......(還) – Fildor

回答

2

ContinueWith具體狀態備註:

如果通過continuationOptions參數不符合規定的標準,延續,延續任務將被取消,而不是調度。

由於您爲前件指定的標準未滿足(即未取消),因此延續被設置爲取消。您等待取消的任務,因此導致DoAsync發生故障,操作取消異常。