TaskCreationOptions.AttachedToParent, родительская задача не ожидает завершения дочернего процесса - PullRequest
0 голосов
/ 17 октября 2018

Рассмотрим следующий фрагмент

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 голосов
/ 17 октября 2018

Поскольку вы печатаете Parent done.. из внутри родительской задачи.На этом этапе родительская задача все еще выполняется, и присоединенные дочерние элементы не имеют значения.

Только когда код для задачи возвращает элемент управления обратно в TPL, он считает, что какие-либо дочерние элементы являютсяприсоединенный и, следовательно, следует ли отмечать объект Task как завершенный.

Присоединенные дочерние элементы не"произвольно блокируют выполнение родительской задачи до тех пор, пока эта задача не будет завершена".В противном случае каждая итерация этого цикла for, который также выполняется в родительской задаче, была бы приостановлена, и создание задач в цикле было бы бессмысленным.

0 голосов
/ 17 октября 2018

Задача твоих родителей - сделать детей.Это делает и закончил.Дети должны заботиться о себе после этого.

Если вы хотите, чтобы ваш родитель ждал своих детей, вы можете сделать что-то вроде следующего:

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..");
...