考虑下面的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
你是指功能?从技术上讲,你几乎是自己创建了一个场景如果您在创建标记后立即取消该标记,请查看会发生什么。 –