考虑以下代码段
var task = Task.Factory.StartNew(() =>
{
Console.WriteLine("Parent starting..");
for (var i = 0; i < 10; ++i)
Task.Factory.StartNew(obj =>
{
Console.WriteLine($"\tChild #{obj} starting...");
Thread.Sleep(1000);
Console.WriteLine($"\tChild #{obj} done..");
}, i, TaskCreationOptions.AttachedToParent);
Console.WriteLine("Parent done..");
});
task.Wait();
哪个输出
Parent starting..
Parent done..
Child #0 starting...
Child #2 starting...
Child #9 starting...
Child #5 starting...
Child #1 starting...
Child #6 starting...
Child #4 starting...
Child #3 starting...
Child #7 starting...
Child #0 done..
Child #1 done..
Child #8 starting...
Child #6 done..
Child #3 done..
Child #5 done..
Child #4 done..
Child #9 done..
Child #2 done..
Child #7 done..
Child #8 done..
这怎么可能?该文档明确指出StartNew
(在父级上)具有默认的创建选项,这不会拒绝子级附加到子级。
为什么task.Wait()
在孩子完成之前不会阻止父级?
答案 0 :(得分:2)
您的父母的任务是生育孩子。它完成了。之后,孩子需要照顾自己。
如果您希望您的父母等待其子女,则可以执行以下操作:
var task = Task.Factory.StartNew(() =>
{
System.Console.WriteLine("Parent starting..");
var childTasks = new Task[10];
for (var i = 0; i < 10; ++i)
{
childTasks[i] = Task.Factory.StartNew(obj =>
{
System.Console.WriteLine($"\tChild #{obj} starting...");
Thread.Sleep(1000);
System.Console.WriteLine($"\tChild #{obj} done..");
}, i, TaskCreationOptions.AttachedToParent);
}
Task.WaitAll(childTasks);
});
task.Wait();
System.Console.WriteLine("Parent done..");
答案 1 :(得分:2)
因为您是从父任务中的中打印Parent done..
的。此时,父任务仍在执行,附加的子项无关。
仅当任务的代码将控制返回到TPL时,它才考虑是否附加了任何子代,并因此考虑是否将 附加的子项不是 “任意阻止父任务执行,直到该任务完成”。如果是这样,该Task
对象标记为已完成。 / p>
for
循环的每次迭代(也在父任务中运行)将被挂起,从而使在循环中创建任务变得毫无意义。