Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning value from Parent-Child tasks

In the snippet below, a task creates two child tasks using the TaskCreationOptions.AttachedToParent, which means the parent task will wait for the child tasks to finish.

Question is - why doesn't the parent task return correct value [102]? Does it first determine its return value and then wait for the child tasks to finish. If so, then what is the point of creating parent-child relationship?

void Main()
{
Console.WriteLine ("Main start.");
int i = 100;

Task<int> t1 = new Task<int>(()=> 
{
    Console.WriteLine ("In parent start");
    Task c1 = Task.Factory.StartNew(() => {
        Thread.Sleep(1000);
        Interlocked.Increment(ref i);
        Console.WriteLine ("In child 1:" + i);
    }, TaskCreationOptions.AttachedToParent);

    Task c2 = Task.Factory.StartNew(() => {
        Thread.Sleep(2000);
        Interlocked.Increment(ref i);           
        Console.WriteLine ("In child 2:" + i);
    }, TaskCreationOptions.AttachedToParent );

    Console.WriteLine ("In parent end");
    return i;
}); 

t1.Start();
Console.WriteLine ("Calling Result.");
Console.WriteLine (t1.Result);
Console.WriteLine ("Main end.");
}

The output:

Main start.
Calling Result.
In parent start
In parent end
In child 1:101
In child 2:102
100
Main end.
like image 506
thewpfguy Avatar asked May 27 '13 10:05

thewpfguy


People also ask

What is the difference between attached and detached child tasks?

A detached child task is a task that executes independently of its parent. An attached child task is a nested task that is created with the TaskCreationOptions.

What is a parent task?

Parent Task is a high-level item within task breakdown that is specified with greater detail by a number of related sub-tasks or child tasks. It is the root task that subordinates its sub-tasks and defines how they should be performed and related to each other.


1 Answers

The problem is that you create c1 and c2 as separate tasks but then return i immediately from t1 before c1 and c2 have incremented i.

Thus, the return value from t1 is captured at that point, and is still 100.

As you noted, there isn't much point in a parent/child relationship for this arrangement; but there are plenty of cases where it does make sense.

A common use is just so that the parent task does not complete until its child tasks have completed, but if you require the parent task to wait for its children before returning a value, you will not be able to do it like this.

Of course, you can fix it by adding

Task.WaitAll(c1, c2);

just before the return i;. I know it's not what you're asking, but I just wanted to point that out anyway.

like image 72
Matthew Watson Avatar answered Oct 05 '22 07:10

Matthew Watson