考虑以下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();
第一个continuation设置为state cancelled(因为它的TaskContinuationOptions值导致它不能运行),而没有将令牌设置为取消。所以最后一个延续确实在这里运行。