我试图了解 .net 任务在附加子项时的行为。
我有以下测试代码:
void Test()
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
Task child = null;
var parent = Task.Factory.StartNew(() =>
{
child = Task.Factory.StartNew(() =>
{
while (!token.IsCancellationRequested)
Thread.Sleep(100);
token.ThrowIfCancellationRequested();
}, token, TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
}, token);
Thread.Sleep(500);
Debug.WriteLine("State of parent before cancel is {0}", parent.Status);
Debug.WriteLine("State of child before cancel is {0}", child.Status);
tokenSource.Cancel();
Thread.Sleep(500);
Debug.WriteLine("State of parent is {0}", parent.Status);
Debug.WriteLine("State of child is {0}", child.Status);
}
结果是:
State of parent before cancel is WaitingForChildrenToComplete
State of child before cancel is Running
A first chance exception of type 'System.OperationCanceledException' occurred in mscorlib.dll
State of parent is RanToCompletion
State of child is Canceled
显然父任务状态不是Canceled
,即使
两个任务共享 token ,并附加子项。
如何让父任务在发生取消时返回状态 Canceled
?
注意
如果我抛出异常,两个任务都会返回 Faulted
。
最佳答案
这是 MSDN 上规定的预期行为。父任务必须 wait (向下滚动到取消部分)子任务。父任务必须处理所有良性故障(如取消)。
要使您的父任务失败,只需等待并传递 token :
Task child = null;
var parent = Task.Factory.StartNew(() =>
{
child = Task.Factory.StartNew(() =>
{
while (!token.IsCancellationRequested) Thread.Sleep(100);
token.ThrowIfCancellationRequested();
}, token, TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
// This is the magic line.
child.Wait(token);
}, token);
如果您使用这段代码来做一些有成效的事情,而不仅仅是为了测试,您还应该考虑使用支持 async
委托(delegate)的简化的 Task.Run()
Task.Factory.StartNew()
。这article很有趣。
关于c# - 子任务取消,父任务完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28564074/