Monday, 27 May 2013

TPL: Parent-Child Tasks and Captured Variables

What do you think will be the return value of the Task named “parentTask”?

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

Task<int> parentTask = new Task<int>(()=>
{
Console.WriteLine ("In parent start");

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

Task childTask2 = 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;
});

parentTask.Start();

Console.WriteLine ("Calling Result.");
//next statement will wait on the task
Console.WriteLine (parentTask.Result);

Console.WriteLine ("Main end.");
}

If a parent-child task hierarchy is set by using TaskCreationOptions.AttachedToParent when creating child tasks, then the parent task waits for all the child tasks to finish. But just because the parent waits for its children to finish, it doesn’t mean it would wait for them before determining its return value.

In the sample above, the line parentTask.Result is a blocking call and so it would wait for the parentTask to finish. But still the increments in the child tasks do not affect the captured variable “i”. The parentTask would need to explicitly wait for the child tasks to return the correct value.

The output of above sample is:


Main start.
Calling Result.
In parent start
In parent end
In child 1:101
In child 2:102
100
Main end.

No comments:

Post a Comment

Note: only a member of this blog may post a comment.