如何设置动态并行任务执行而不是手动调用分派?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何设置动态并行任务执行而不是手动调用分派?相关的知识,希望对你有一定的参考价值。

在这种情况下,最佳方法是什么,其中需要运行多个任务,具体取决于给定的参数。请参阅以下代码:

void Mapping() 
{
    if(param.IsProgram1) {
        //                   spGetProgram1() is a stored procedure call
        MapProgram1(context, spGetProgram1().GetIterator());

        if(param.IsProgram2) {
           MapProgram2(context, spGetProgram2().GetIterator());
        }
    }

    if(param.IsProgram3) {
       MapProgram3(context, spGetProgram23().GetIteratior());
    }
}



 static void MapProgram1(context, IEnumerable<IDataRecord> records) {
  // map records to context
 }

 static void MapProgram2(context, IEnumerable<IDataRecord> records) {
  // map records to context
 }

 static void MapProgram3(context, IEnumerable<IDataRecord> records) {
  // map records to context
 }

我想重构这个并且并行运行任务。我目前的方法是将任务存储在字典中并根据给定的参数调用它

 var tasks = new Dictionary<string, Task<IEnumerable<IDataRecord>>>()
 {
            { "MapProgram1", null },
            { "MapProgram2", null },
            { "MapProgram3", null },
 }

 if(param.IsProgram1) tasks["MapProgram1"].Value = Task.Run(() => spGetProgram1().GetIterator())

 ... ...


 tasks.WaitAll(tasks.Select(t => t.Value).ToArray());

然后获取结果并调用相应的映射方法

  foreach(var t in tasks.Where(t => t.Value != null))
        {
            if(t.Key == "MapProgram1")
            {
                MapProgram1(context, t.Value.Result);
            }

            if (t.Key == "MapProgram2")
            {
                MapProgram2(context, t.Value.Result);
            }

            .....
        }

我确信在这方面有一个更清晰的方法,我不需要手动调用方法。

答案

我不确定我是否按照你的榜样;但是,一般来说,如果你想并行执行任务并有条件地选择要执行的任务,你可能会做这样的事情......

    async Task Run() {
        List<Task<IResult>> tasks = new List<Task<IResult>>();
        if (someCondition) {
            tasks.Add(RunSome(someParams));
        }
        if (othercondition) {
            tasks.Add(RunOther(otherParam));
        }
        IResult[] results = await Task.WhenAll(tasks);
        foreach (var result in results) {
            if (result is SomeResult someResult) {
                // Handle some result
            }
            else if (result is OtherResult otherResult) {
                // Handle other result
            }
        }
    }

    static async Task<SomeResult> RunSome(someParams) {
        // Run something
    }

    static async Task<OtherResult> RunOther(otherParams) {
        // Run other thing
    }

    interface IResult {
    }

    class SomeResult : IResult {
    }

    class OtherResult: IResult {
    }

将要并行执行的任务添加到列表中,让每个任务返回某个结果类型的实例,然后在完成所有任务后检查结果。

另一答案

您可以使用Parallel.ForEach做很多事情,即调整并行度等

然而,它确实取决于你的工作量和你想要达到的目标,但这可能会让你深思熟虑

var list = new List<Stuff>();

Parallel.ForEach(list, (item) =>
{
    switch(item,ConditionType)
    {
      case ConditionType.First : DoSomethingWithItem(item); break;
      case ConditionType.Second : DoSomethingElseWithItem(item); break;
    }
});

更多资源

Parallel.ForEach Method

Msdn : How to: Write a Simple Parallel.ForEach Loop

以上是关于如何设置动态并行任务执行而不是手动调用分派?的主要内容,如果未能解决你的问题,请参考以下文章

Java中的方法调用分析!详细解析静态分派和动态分派的执行过程

Java静态分派与动态分派

多态方法调用的解析和分派

关于多线程提高程序执行速率的问题

在 C# 并行任务中为多个服务调用创建并行任务

Java编程思想学习(十六) 并发编程