我以爲CancellationToken/CancellationTokenSource系統有點像C++ volatile bool bFlagCancelled
,這意味着任務的取消是自願的,並且依賴任務本身來不時檢查它是否被取消並拋出異常,明確地或通過致電ThrowIfCancellationRequested()
。不檢查它是否被取消的TPL任務,是否仍被取消?
但是如果我在StartNew()
之後立即致電取消,則任務停止,並且調用Wait()
將拋出TaskCanceledException
。
例如,此代碼:
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
Task task = Task.Factory.StartNew(
() =>
{
Console.WriteLine("start sleep");
Thread.Sleep(1000);
Console.WriteLine("sleep ended");
}
, token);
// Thread.Sleep(1);
source.Cancel();
Console.WriteLine("start wait");
task.Wait();
Console.WriteLine("wait ended");
我得到這樣的輸出:
start wait Exception: System.AggregateException: One or more errors occurred. ---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
但是,如果我去掉// Thread.Sleep(1);
,則行爲的變化,我得到這樣的輸出:
start sleep start wait sleep ended wait ended
現在我想也許這是因爲task.Start()
尚未被調用,bu t據我瞭解,StartNew()
在返回之前調用task.Start()
- 這就是爲什麼它沒有同步成本,建議與創建new Task
並自己調用task.Start()
。
那麼這意味着在某些情況下,即使不檢查取消標記,任務也會自動取消。這是發生這種情況的唯一情況嗎,還是有更多的情況發生?
感謝您的回答。有沒有其他的情況發生,或者這是唯一的嗎? – sashoalm
@sashoalm每當任務尚未轉變爲「正在運行」。例如,如果您在任務中調用「ContinueWith」並取消該任務,則繼續也會被取消 –
再次感謝。我剛剛發現http://stackoverflow.com/a/10444108/492336,他們解釋說,將'token'傳遞給'StartNew'是爲了實現這種行爲,並且確實不會將令牌傳遞給'StartNew()'與取消註釋「//睡眠(1)」相同的效果。 – sashoalm