TaskCreationOptions.AttachedToParent,父任务不等待子完成

时间:2018-10-17 08:50:35

标签: c# task

考虑以下代码段

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()在孩子完成之前不会阻止父级?

2 个答案:

答案 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循环的每次迭代(也在父任务中运行)将被挂起,从而使在循环中创建任务变得毫无意义。