简体   繁体   中英

Why parent task finishes before his children tasks?

In my code parent task finishes before his children tasks. Why does it happen?

I thought parent task shouldn't finish before child task finishes.

My code:

var parent = Task.Run(() =>
{
    int[] tab = new int[3];

    new Task(() =>
    {
        tab[0] = 9;
        Thread.Sleep(4000);
        Console.WriteLine("Child1");
    }, TaskCreationOptions.AttachedToParent).Start();

    new Task(() =>
    {
        tab[1] = 2;
        Thread.Sleep(2000);
        Console.WriteLine("Child2");
    }, TaskCreationOptions.AttachedToParent).Start();

    new Task(() =>
    {
        tab[2] = 3;
        Thread.Sleep(1000);
        Console.WriteLine("Child3");
    }, TaskCreationOptions.AttachedToParent).Start();

    Console.WriteLine("I am here");
    return tab;
});

var finalTask = parent.ContinueWith((a) =>
{
    a.Result.ToList().ForEach(Console.WriteLine);   
});

finalTask.Wait();
Console.WriteLine("Out of threads");
Console.ReadLine();

Results:

I am here
9
2
3
Out of threads
Child3 Child2
Child1

I think, I found a reason: "Parent tasks implicitly prevent child tasks from attaching to them if they are created by calling the Task.Run method." So, I shouldn't use Task.Run() , I should use Task.Factory.StartNew() instead.

Because you are not waiting for the parent tasks by calling parent.Wait(); . See Attached and Detached Child Tasks for more information. specifically the example shown.

Though using Task.Factory.StartNew() with TaskCreationOptions.AttachedToParent option is best option to attach child thread with parent. But another way could have been by using Task.WaitAll in parent thread function. Only advantage is that one can use a timeout time with WaitAll .

One can re-write block as:

var parent = Task.Run(() =>
{
    int[] tab = new int[3];

    var child1 = Task.Run(() =>
    {
        tab[0] = 9;
        Thread.Sleep(4000);
        Console.WriteLine("Child1");
    });

    var child2 = Task.Run(() =>
    {
        tab[1] = 2;
        Thread.Sleep(2000);
        Console.WriteLine("Child2");
    });

    var child3 = Task.Run(() =>
    {
        tab[2] = 3;
        Thread.Sleep(1000);
        Console.WriteLine("Child3");
    });

    Task.WaitAll(child1, child2, child3);  //Wait for all 3 threads to complete. 

    Console.WriteLine("I am here");
    return tab;
});

var finalTask = parent.ContinueWith((a) =>
{
    a.Result.ToList().ForEach(Console.WriteLine);
});

finalTask.Wait();
Console.WriteLine("Out of threads");
Console.ReadLine();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM