考慮下面的C#代碼:爲什麼在取消父項時未觸發子任務的任務延續?
CancellationTokenSource tCancelSource = new CancellationTokenSource();
var tTask = Task.Factory.StartNew
(
() =>
{
// Start child
Task.Factory.StartNew
(() =>
{
Thread.Sleep(2000);
Console.WriteLine("A");
tCancelSource.Token.ThrowIfCancellationRequested();
}
, tCancelSource.Token
, TaskCreationOptions.AttachedToParent
, TaskScheduler.Current
)
.ContinueWith
(
t =>
{
Console.WriteLine("B");
}
, tCancelSource.Token, TaskContinuationOptions.AttachedToParent
, TaskScheduler.Current
);
}
, tCancelSource.Token, TaskCreationOptions.PreferFairness
, TaskScheduler.Current
)
.ContinueWith
(t => Console.WriteLine("C"));
Thread.Sleep(500);
tCancelSource.Cancel();
tTask.Wait();
Console.WriteLine("Done"); Console.Read();
子任務的延續不會觸發,即B沒有打印到控制檯。註釋掉調用取消將打印B.
觀察:
A
C
預計
A
B
C
看來,如果家長被取消子任務的繼續不解僱,但我無法找到這個記錄。任何人都知道爲什麼/這裏發生了什麼,或者這將記錄在哪裏?
編輯:
我忘了將取消標記傳遞給最後的延續。事實上,我發現文檔內容如下: 「[...]如果先行者被取消,繼續將不會開始」,但是我被選項TaskContinuation.OnlyOnCanceled弄糊塗了。這種情況是可能的,例如
CancellationTokenSource tSource = new CancellationTokenSource();
Task tTest = Task.Factory.StartNew
(
() =>
{
throw new Exception("foobar");
}, tSource.Token).ContinueWith(t =>
{
Console.WriteLine("A " + t.Status);
}
, tSource.Token
, TaskContinuationOptions.NotOnFaulted
, TaskScheduler.Current
)
.ContinueWith
(
t =>
{
Console.WriteLine("B " + t.Status);
}
, tSource.Token
);
tTest.Wait();
Console.Read();
第一延續設置爲取消狀態(如它的TaskContinuationOptions值使其不運行),而令牌被設置爲取消。所以最後的延續在這裏運行。
我在文檔中錯過了「[...]如果先行者被取消了,繼續將不會開始。」我有點困惑的選項TaskContinuationOptions.OnlyOnCanceled,我似乎無法想象的情況下,前提取消,使延續運行(先前在取消狀態)。 – Marcus
你是指功能?從技術上講,你幾乎是自己創建了一個場景如果您在創建標記後立即取消該標記,請查看會發生什麼。 –