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

问题描述 投票:1回答:2

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

重点是:

我有一堆列表,并且每个列表中都有一些要做的事情,并且需要使它们尽可能多地并行运行并且可以减少阻塞,并且每次完成每个subBunchOfThingsTodo时(这意味着每个事情都要在里面完成)它是平行完成的)它做了一些事情(DoSomethingAfterEveryThingToDoOfThisSubBunchOfThingsAreDone())。

e.g:

ちょfすch ch f f gととど

  • 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);
}
c# multithreading task
2个回答
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; }
}

-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团队,建议“良好”的解决方案:

    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);
© www.soinside.com 2019 - 2024. All rights reserved.