从父子任务返回值

时间:2013-05-27 10:08:53

标签: c# task-parallel-library

在下面的代码段中,任务使用TaskCreationOptions.AttachedToParent创建两个子任务,这意味着父任务将等待子任务完成。

问题是 - 为什么父任务没有返回正确的值[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(() => {
        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.");
}

输出:

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

2 个答案:

答案 0 :(得分:5)

问题在于您将c1c2创建为单独的任务,但在it1之前立即从c1返回c2增加了i

因此,此时会捕获t1的返回值,并且仍为100

正如您所指出的,这种安排在父母/子女关系中没有太大意义;但是有很多情况下 有意义。

一个常见的用途就是父任务在子任务完成之前不会完成,但是如果你需要父任务在返回一个值之前等待它的子项,你将无法像这样做

当然,你可以通过添加

来解决它
Task.WaitAll(c1, c2);

就在return i;之前。我知道这不是你问的问题,但我只是想指出这一点。

答案 1 :(得分:-1)

如前所述,i的值在递增之前返回。以这种方式更改代码它返回预期值(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.");
 }

我所做的只是从子任务中取出Thread.Sleep(1000)到父任务。现在,在变量递增后返回结果。