从父母返回价值
在下面的代码片段中,任务使用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.
  问题是,你创建c1和c2作为单独的任务,但再回到i立即从t1之前c1和c2都增加i 。 
  因此, t1的返回值在该点被捕获,并且仍然是100 。 
正如你所指出的,这种安排在亲子关系方面没有多少意义。 但有很多情况下它是有道理的。
一个常用的用法是,父任务在其子任务完成之前不会完成,但如果您需要父任务在返回值之前等待子任务,那么您将无法像这样完成任务。
当然,你可以通过添加来修复它
Task.WaitAll(c1, c2);
  就在return i;之前return 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)到父任务。 变量递增后,结果会立即返回。
链接地址: http://www.djcxy.com/p/71733.html