并行任务和子任务工作流程

时间:2018-03-02 12:00:46

标签: c# multithreading task

我是C#线程和任务的新手,我正在尝试开发工作流程,但没有成功,可能是因为我将任务与迭代混合......

重点是:

我有一堆列表,每个列表中都有一些要做的事情,并且需要让它们尽可能多地并行运行并且阻塞性更小,并且只要每个subBunchOfThingsTodo完成(这意味着内部要做的每件事都是平行完成的。它做了一些事情(DoSomethingAfterEveryThingToDoOfThisSubBunchOfThingsAreDone())。

e.g:

bunchOfSubBunchsOfThingsTodo

  • subBunchOfThingsTodo

    • ThingToDo1
    • ThingToDo2
  • subBunchOfThingsTodo

    • ThingToDo1
    • ThingToDo2
    • ThingToDo3
  • subBunchOfThingsTodo

    • ThingToDo1
    • ThingToDo2 ...

这就是我尝试的方式,但不幸的是,每次迭代都会等待前一个onOfThingsToDo,我需要它们并行工作。 事情要做同样的事情,他们等待前一件事开始......

List<X> bunchOfSubBunchsOfThingsTodo = getBunchOfSubBunchsOfThingsTodo();     
foreach (var subBunchOfThingsToDo in bunchOfSubBunchsOfThingsTodo)
{
    int idSubBunchOfThingsToDo = subBunchOfThingsToDo.ThingsToDo.FirstOrDefault().IdSubBunchOfThingsToDo;

    var parent = Task.Factory.StartNew(() =>
    {
        foreach (var thingToDo in subBunchOfThingsToDo.ThingsToDo)
        {
            var child = Task.Factory.StartNew(() =>
            {
               //Do some stuff with thingToDo... Here I call several bussines methods
            });
        }
    });

    parent.Wait();
    DoSomethingAfterEveryThingToDoOfThisSubBunchOfThingsAreDone(idSubBunchOfThingsToDo);
}

2 个答案:

答案 0 :(得分:1)

您可能想尝试使用 Task.WhenAll 并使用linq来生成一系列热门任务:

static async void ProcessThingsToDo(IEnumerable<ThingToDo> bunchOfThingsToDo)
{
    IEnumerable<Task> GetSubTasks(ThingToDo thing) 
        => thing.SubBunchOfThingsToDo.Select( async subThing => await Task.Run(subThing));

    var tasks = bunchOfThingsToDo
        .Select(async thing => await Task.WhenAll(GetSubTasks(thing)));

    await Task.WhenAll(tasks);
}

通过这种方式,您可以在单独的任务上运行每个 subThingToDo ,并且每个 thingToDo

只能获得由所有子任务组成的一个任务

修改

在此示例中,ThingToDo是一个相当简单的类:

class ThingToDo
{
    public IEnumerable<Action> SubBunchOfThingsToDo { get; }
}

答案 1 :(得分:-2)

只需更改代码,您就可以尝试这种方式:

    var toWait = new List<Task>();
    List<X> bunchOfSubBunchsOfThingsTodo = getBunchOfSubBunchsOfThingsTodo();     
    foreach (var subBunchOfThingsToDo in bunchOfSubBunchsOfThingsTodo)
    {
        int idSubBunchOfThingsToDo = subBunchOfThingsToDo.ThingsToDo.FirstOrDefault().IdSubBunchOfThingsToDo;

        var parent = Task.Factory.StartNew(() =>
        {
            Parallel.ForEach(subBunchOfThingsToDo.ThingsToDo,
                thingToDo =>
                {
                        //Do some stuff with thingToDo... Here I call several bussines methods
                });
        });

        //parent.Wait();
        var handle = parent.ContinueWith((x) =>
        {
            DoSomethingAfterEveryThingToDoOfThisSubBunchOfThingsAreDone(idSubBunchOfThingsToDo);
        })
        .Start();

        toWait.Add(handle);
    }

    Task.WhenAll(toWait);

感谢downvoters团队,建议“好”&#39;溶液:

    var bunchOfSubBunchsOfThingsTodo = getBunchOfSubBunchsOfThingsTodo();
    var toWait = bunchOfSubBunchsOfThingsTodo
        .Select(subBunchOfThingsToDo =>
        {
            return Task.Run(() =>
            {
                int idSubBunchOfThingsToDo = subBunchOfThingsToDo.ThingsToDo.FirstOrDefault().IdSubBunchOfThingsToDo;

                Parallel.ForEach(subBunchOfThingsToDo.ThingsToDo,
                    thingToDo =>
                    {
                        //Do some stuff with thingToDo... Here I call several bussines methods
                    });

                DoSomethingAfterEveryThingToDoOfThisSubBunchOfThingsAreDone(idSubBunchOfThingsToDo);
            });
        });

    Task.WhenAll(toWait);