在C#中并行运行三种方法的最简单方法


72

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

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

每个函数彼此独立,并且可以在没有死锁的情况下并行计算。
没有完成包含方法直到所有三个方法都完成时,并行计算这些方法的最简单方法是什么?


您只对并行任务库解决方案感兴趣吗?那么直接的Delegate.BeginInvoke()甚至Thread.Start()呢?
sll

他想等待所有结果-您可以按照自己的建议执行此操作,但必须自己完成同步-恕我直言,只要没有确凿的理由不做,就应该使用Task-这将变得更加重要如果C#/ async上线
卡斯滕

我发现的所有线程启动示例都不会等到函数组完成之后。
PlTaylor 2011年

1
不,他们没有,您应该真正使用Task-Library处理此类内容。恕我直言,MS正在使用异步方法来推动这种方法,它确实是一个不错的库(几乎与F#的async-workflows:D一样好)
Carsten

Answers:


128

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

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()不能保证它们确实可以并行运行,也不能保证动作执行的顺序。


4
这会等待所有并行任务完成吗?
乔纳森

2
对于我所做的所有搜索,似乎大多数人都忽略了这个简单的示例。感谢您的快速回复和出色的回答。
PlTaylor 2011年

5
@Jonathan它将等待。该构造类似于启动多个任务然后调用Task.WaitAll
Libor 2013年

如何从不同的方法获取返回值
F11,19年

20

您也可以通过任务执行此操作(如果以后需要取消或类似结果,则更合适)

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

7
使用start new可能不是一个好主意,请参阅:(blog.stephencleary.com/2013/08/startnew-is-dangerous.html
Microsoft Developer

3
@dotNETNinja现在是正确的-这个答案已经很老了(如您所见)-没有异步了-无论如何,您都可以Task.Run按照提供的链接的建议进行切换-可以使用.net4.5(或更高版本)
卡斯滕2014年

我也有类似的在这里..什么stackoverflow.com/questions/30261335/...
Ziggler


3

若要运行彼此独立的并行方法,也可以使用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


0
var task1 = SomeLongRunningTask();
var task2 = SomeOtherLongRunningTask();

await Task.WhenAll(task1, task2);

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


1
Parallel还使用当前线程执行操作,因此它不会阻塞等待操作完成的线程。如果您需要并行执行受CPU约束的同步操作,那么这是一个更好的选择。
Eli Arbel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.