87

I have three methods that I call to do some number crunching that are as follows

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

Each of the functions is independent of each other and can be computed in parallel with no dead locks.
What is the easiest way to compute these in parallel without the containing method finishing until all three are done?

Tomas Walek
  • 2,516
  • 2
  • 23
  • 37
PlTaylor
  • 7,345
  • 11
  • 52
  • 94
  • You only interested in task parallel lib solution? What about straightforward Delegate.BeginInvoke() or even Thread.Start()? – sll Sep 06 '11 at 13:18
  • he want to wait for all results - you can do this with what you suggest but have to do the sync by yourself - IMHO you should use Task as long there isn't some really good reason not to do - this will get even more important if C#/async goes live – Random Dev Sep 06 '11 at 13:22
  • All the thread start examples I have found don't wait until the group of functions complete. – PlTaylor Sep 06 '11 at 13:25
  • 1
    No they don't and you should really use the Task-Library for this kind of stuff. IMHO MS is pushing this approach with async and it is really a nice lib (almost as good as F#'s async-workflows :D ) – Random Dev Sep 06 '11 at 13:40

5 Answers5

148

See the TPL documentation. They list this sample:

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

So in your case this should just work:

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

EDIT: The call returns after all actions have finished executing. Invoke() is does not guarantee that they will indeed run in parallel, nor does it guarantee the order in which the actions execute.

Sander Rijken
  • 21,376
  • 3
  • 61
  • 85
  • 5
    Will this wait until all Parallel tasks are completed? – Jonathan Sep 06 '11 at 13:21
  • 2
    For all the searching I have done, it seems as though most people have left out this simple example. Thanks for the quick response and great answer. – PlTaylor Sep 06 '11 at 13:24
  • 5
    @Jonathan It will wait. The construct is similar to starting several tasks and then calling `Task.WaitAll`. – Libor Jun 15 '13 at 19:12
  • 1
    how to get return values from different methods – F11 Oct 15 '19 at 08:51
  • This here seems a clever approach: https://social.msdn.microsoft.com/Forums/vstudio/en-US/95b7b466-ee41-4a95-a1b5-c4d5b5bc1198/how-do-i-get-the-result-from-parallelinvoke-method?forum=parallelextensions – Anytoe Mar 07 '23 at 15:59
29

You can do this with tasks too (nicer if you later need Cancellation or something like results)

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);
Dave New
  • 38,496
  • 59
  • 215
  • 394
Random Dev
  • 51,810
  • 9
  • 92
  • 119
  • 9
    Possibly not a good idea to use start new see: (http://blog.stephencleary.com/2013/08/startnew-is-dangerous.html) – Microsoft Developer Dec 12 '14 at 14:16
  • 5
    @dotNETNinja true now - this answer is quite old (as you can see) - there was no async then - anyhow you can just switch it with [`Task.Run`](http://msdn.microsoft.com/en-us/library/hh195051(v=vs.110).aspx) as adviced by the link you provided - given you may use .net4.5 (or newer) – Random Dev Dec 12 '14 at 15:36
  • I have something similar here.. http://stackoverflow.com/questions/30261335/call-methods-parallel-and-combine-results – Ziggler May 19 '15 at 15:06
3

To run parallel methods which are independent of each other ThreadPool.QueueUserWorkItem can also be used. Here is the sample method-

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

More detail about this function can be found here:
http://newapputil.blogspot.in/2016/03/running-parallel-tasks-using.html

Shai
  • 3,659
  • 2
  • 13
  • 26
nvivekgoyal
  • 484
  • 9
  • 15
3

In .NET 4, Microsoft introduced the Task Parallel Library which was designed to handle this kind of problem, see Parallel Programming in the .NET Framework.

Dave New
  • 38,496
  • 59
  • 215
  • 394
Shiraz Bhaiji
  • 64,065
  • 34
  • 143
  • 252
2
var task1 = SomeLongRunningTask();
var task2 = SomeOtherLongRunningTask();

await Task.WhenAll(task1, task2);

The benefit of this over Task.WaitAll is that this will release the thread and await the completion of the two tasks.

Brett Mealor
  • 111
  • 1
  • 1
  • 7
  • If you just want to run stuff at the same time, but you don't care about deep stuff, this is the best/simplest and most modern way. – Timotei Oros Apr 19 '23 at 09:16