Returning value from Parent

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.

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.


As already said the value of i is returned before it's incremented. changing your code in this way it return the expected value (102):

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(() => {
        Interlocked.Increment(ref i);
        Console.WriteLine ("In child 1:" + i);
    }, TaskCreationOptions.AttachedToParent);

    Thread.Sleep(1000);

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

    Thread.Sleep(1000);

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

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

what I did is simply take out the Thread.Sleep(1000) from the child task to the parent task. The result is returned now after the variable has been incremented.

链接地址: http://www.djcxy.com/p/71734.html

上一篇: Bootbox回调无法正常工作

下一篇: 从父母返回价值