2012-08-26 46 views
3

我已經寫了下面的代碼:任務狀態時取消

CancellationTokenSource tokenSource = new CancellationTokenSource(); 
CancellationToken token = tokenSource.Token; 

int i = 0; 
Console.WriteLine("Calling from Main Thread {0}", System.Threading.Thread.CurrentThread.ManagedThreadId); 

Task t1 = new Task(() => 
{ 
    while (true) 
    { 
     try 
     { 
      token.ThrowIfCancellationRequested(); 
     } 

     catch (OperationCanceledException) 
     { 
      Console.WriteLine("Task1 cancel detected"); 
      break; 
     } 

     Console.WriteLine("Task1: Printing: {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, i++); 
    } 
}, token); 

Task t2 = new Task(() => 
{ 
    while (true) 
    { 
     try 
     { 
      token.ThrowIfCancellationRequested(); 
     } 

     catch (OperationCanceledException) 
     { 
      Console.WriteLine("Task2 cancel detected"); 
      break; 
     } 

     Console.WriteLine("Task2: Printing: {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, i++); 
    } 
}); 

t1.Start(); 
t2.Start(); 
Thread.Sleep(100); 
tokenSource.Cancel(); 

t1.Wait();//wait for thread to completes its execution 
t2.Wait();//wait for thread to completes its execution 
Console.WriteLine("Task1 Status:{0}", t1.Status); 
Console.WriteLine("Task2 Status:{0}", t1.Status); 

我在這裏取消接任務也狀態顯示RanToCompletion,但如果我在兩個任務刪除的等待,那麼就說明我取消狀態.. 。

因爲我取消了任務,我期待在任何情況下,取消狀態...

編輯:從MSDN 通過投擲OperationCanceledException並將其傳遞次請求取消的令牌。執行此操作的首選方法是使用ThrowIfCancellationRequested方法。以這種方式取消的任務轉換爲取消狀態,調用代碼可以使用該狀態來驗證任務是否響應了取消請求。

如果不使用等待或爲WaitAll方法來等待任務,該任務只是將其地位已取消。

回答

6

當你正趕上OperationCanceledException並打破while循環,任務結束優雅和任務狀態會RanToCompletion。

爲了得到一個取消狀態,你要麼需要重新拋出OperationCanceledException或抓不住它。

任務用自己的的CancellationToken拋出 OperationCanceledException承認取消而 令牌是信號狀態,或任務的的CancellationToken是 不已:當

根據MSDN任務狀態將被取消在任務開始執行之前發出信號。有關更多 的信息,請參見Task Cancellation

由於您已經吞下源代碼中的異常,因此任務狀態將爲RanToCompletion。

要獲得關於爲什麼當你刪除等待狀態被取消的問題,很可能是因爲異常尚未捕獲,並且取消狀態已經在較早時間得到遏制。 此行爲不應被視爲可靠和可重複。

+0

感謝齊亞德。但是,當我刪除的任務,然後我得到它正在創造一些混亂的取消狀態等待.. –

+0

更新從MSDN鏈接的問題:仍然搞不清我已經更新了聲明。它是否與你最後的陳述相矛盾? –

+0

@RaoBHavik我認爲當您執行Wait時狀態爲Cancelled的事實完全是巧合。實際上,如果您替換Thread.Sleep(5000)這兩個等待,任務狀態可能會是RanToCompletion。 –