【问题标题】:Simplest way to run three methods in parallel in C#在 C# 中并行运行三个方法的最简单方法
【发布时间】:2011-09-06 13:13:49
【问题描述】:

我调用了三种方法来进行一些数字运算,如下所示

results.LeftFront.CalcAi();  
results.RightFront.CalcAi();  
results.RearSuspension.CalcAi(geom, vehDef.Geometry.LTa.TaStiffness, vehDef.Geometry.RTa.TaStiffness);

每个函数相互独立,可以并行计算,没有死锁。
在所有三个都完成之前,在不完成包含方法的情况下并行计算这些的最简单方法是什么?

【问题讨论】:

  • 您只对任务并行库解决方案感兴趣?直接的 Delegate.BeginInvoke() 甚至 Thread.Start() 怎么样?
  • 他想等待所有结果 - 您可以按照您的建议执行此操作,但必须自己进行同步 - 恕我直言,您应该使用 Task,只要没有什么很好的理由不做 - 如果 C#/async 上线,这将变得更加重要
  • 我找到的所有线程启动示例不要等到函数组完成。
  • 不,他们没有,你真的应该使用任务库来处理这类事情。恕我直言,MS 正在通过异步推动这种方法,它确实是一个不错的库(几乎与 F# 的异步工作流一样好:D)

标签: c# parallel-processing task-parallel-library


【解决方案1】:

请参阅TPL documentation。他们列出了这个样本:

Parallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork());

所以在你的情况下这应该可以工作:

Parallel.Invoke(
    () => results.LeftFront.CalcAi(),
    () => results.RightFront.CalcAi(),
    () => results.RearSuspension.CalcAi(geom, 
                                        vehDef.Geometry.LTa.TaStiffness, 
                                        vehDef.Geometry.RTa.TaStiffness));

编辑:在所有操作完成执行后调用返回。 Invoke() 不保证它们确实会并行运行,也不保证动作执行的顺序。

【讨论】:

  • 这会等到所有并行任务完成吗?
  • 对于我所做的所有搜索,似乎大多数人都忽略了这个简单的例子。感谢您的快速响应和出色的回答。
  • @Jonathan 它会等待。该构造类似于启动多个任务然后调用Task.WaitAll
  • 如何获取不同方法的返回值
【解决方案2】:

您也可以对任务执行此操作(如果您以后需要取消或类似结果的东西会更好)

var task1 = Task.Factory.StartNew(() => results.LeftFront.CalcAi());
var task2 = Task.Factory.StartNew(() => results.RightFront.CalcAi());
var task3 = Task.Factory.StartNew(() =>results.RearSuspension.CalcAi(geom, 
                              vehDef.Geometry.LTa.TaStiffness, 
                              vehDef.Geometry.RTa.TaStiffness));

Task.WaitAll(task1, task2, task3);

【讨论】:

【解决方案3】:

在 .NET 4 中,Microsoft 引入了旨在处理此类问题的任务并行库,请参阅 Parallel Programming in the .NET Framework

【讨论】:

    【解决方案4】:

    要运行彼此独立的并行方法,也可以使用 ThreadPool.QueueUserWorkItem。这是示例方法-

    public static void ExecuteParallel(params Action[] tasks)
    {
        // Initialize the reset events to keep track of completed threads
        ManualResetEvent[] resetEvents = new ManualResetEvent[tasks.Length];
    
        // Launch each method in it's own thread
        for (int i = 0; i < tasks.Length; i++)
        {
            resetEvents[i] = new ManualResetEvent(false);
            ThreadPool.QueueUserWorkItem(new WaitCallback((object index) =>
                {
                    int taskIndex = (int)index;
    
                    // Execute the method
                    tasks[taskIndex]();
    
                    // Tell the calling thread that we're done
                    resetEvents[taskIndex].Set();
                }), i);
        }
    
        // Wait for all threads to execute
        WaitHandle.WaitAll(resetEvents);
    }
    

    关于这个功能的更多细节可以在这里找到:
    http://newapputil.blogspot.in/2016/03/running-parallel-tasks-using.html

    【讨论】:

      【解决方案5】:
      var task1 = SomeLongRunningTask();
      var task2 = SomeOtherLongRunningTask();
      
      await Task.WhenAll(task1, task2);
      

      与 Task.WaitAll 相比,这样做的好处是这将释放线程并等待两个任务的完成。

      【讨论】:

      • Parallel 也使用当前线程来执行动作,因此它不会阻塞等待动作完成的线程。如果您有需要并行化的同步、受 CPU 限制的操作,这是一个更好的选择。
      猜你喜欢
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多