c# - 父任务不等待子任务

标签 c# .net 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);
}

这是 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;
}

这是 Thing

class Thing
{
    public bool BoolProp { get; set; }
    public int IntProp { get; set; }
}

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

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

最佳答案

父任务实际上是在等待(不是“等待”)子任务。您的问题是代码在没有同步的情况下从多个线程访问 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);

推荐阅读:Parallel TasksDynamic Task Parallelism .

关于c# - 父任务不等待子任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22116846/

相关文章:

c++ - 将位图保存到从中加载的同一文件

c# - 是否可以从 .NET 库代码中检测到不受控制的取消?

c# - 这是正确的实现吗?

c# - 如何从数组中查找字符串并将其分配给 c# asp.net 中的字符串

c# - 此 DateTime 代码与 DateTime.now 有什么不同吗

c# - 如何比较 2 个逗号分隔的字符串值并在现有列表中的同一位置进行更新?

.net - 多线程应用程序中的 Entity Framework : Object not set exception in Oracle. DataAccess

c# - 如何通过提供ID列表从列表中查询对象

c# - 将具有变化值的参数传递给任务 - 行为?

c# - 如何将 Autofac 与 WepApi 2 和 Owin 集成?