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

时间:2017-12-20 06:41:59

标签: c# parallel-processing refactoring task

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

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);
            }

            .....
        }

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

2 个答案:

答案 0 :(得分:0)

您可以使用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

答案 1 :(得分:0)

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

    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 {
    }

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