父任务不等待子任务

Dim*_*tri 4 .net c# task-parallel-library

这是我的代码

static void Main(string[] args)
{
    List<Thing> collection = new List<Thing>
    { 
        new Thing { IntProp = 1, BoolProp = true }, 
        new Thing { IntProp = 1, BoolProp = true }, 
        new Thing { IntProp = 2, BoolProp = true }, 
        new Thing { IntProp = 1, BoolProp = false } 
    };

    int number = 0;

    var task = Task.Factory.StartNew<bool>(() =>
    {
        TaskFactory ts = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously);

        foreach (var item in collection)
        {
            if (item.BoolProp)
            {
                ts.StartNew(() =>
                    number += GetNum1(item.IntProp));
            }
            else
            {
                ts.StartNew(() =>
                    number += GetNum2(item.IntProp));
            }
        }

        return true;
    });

    task.Wait();

    Console.WriteLine(number);
}
Run Code Online (Sandbox Code Playgroud)

这里是定义GetNum1GetNum2

static int GetNum1(int num)
{
    for (int i = 0; i < 1000000000; i++) { } // simulate some job

    return 10;
}

static int GetNum2(int num)
{
    for (int i = 0; i < 500000000; i++) { } // simulate some job

    return 3;
}
Run Code Online (Sandbox Code Playgroud)

这是Thing班级

class Thing
{
    public bool BoolProp { get; set; }
    public int IntProp { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

基本上我正在做的只是创建Thing对象的集合.然后我创建一个单个父任务,它将有几个子任务(它应该等待,我猜).

有一个number变量,它由子任务增加,返回的数量 GetNum1GetNum2方法(10或3).我猜测上面的代码应输出33(10 + 10 + 10 + 3),但输出10代码,因为只等待第一个子任务.如果我将断点放在代码中并逐步进行,那么输出是正确的.为什么会这样呢?是否必须对父任务中的foreach循环执行某些操作?请不要开始问"为什么需要这个"和"没有必要"这样的问题,这只是一个示例代码.

Ste*_*ary 5

父任务实际上正在等待(而不是"等待")子任务.您的问题是代码number从多个线程访问变量而没有同步:

var mutex = new object();
int number = 0;

var task = Task.Factory.StartNew<bool>(() =>
{
    TaskFactory ts = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously);

    foreach (var item in collection)
    {
        if (item.BoolProp)
        {
            ts.StartNew(() =>
            {
                var value = GetNum1(item.IntProp);
                lock (mutex) number += value;
            });
        }
        else
        {
            ts.StartNew(() =>
            {
                var value = GetNum2(item.IntProp);
                lock (mutex) number += value;
            });
        }
    }

    return true;
});

task.Wait();

lock (mutex)
    Console.WriteLine(number);
Run Code Online (Sandbox Code Playgroud)

推荐阅读:并行任务动态任务并行.

  • @ V-SHY:在读取时跳过`lock`有时会起作用,但是线程本地缓存可能会让你搞砸了高级硬件. (2认同)