Simplest way to run three methods in parallel in C#
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.
Execute few methods in parallel
Depending on what kind of processing your methods need to do and if they update GUI elements, you can use the following classes:
- ThreadPool
- BackgroundWorker
- Thread
The answers in this question will help you figure out which is the ideal for your scenario.
Evaluating methods in parallel
I guess the least invasive way is using Parallel.Invoke:
long x, y, z, b;
Parallel.Invoke(
() => x = LongCalculation(123),
() => y = LongCalculation2(345),
() => z = LongCalculation3(678),
() => b = LongCalculation4(910)
);
Call methods parallel and combine results
You can run them as 2 Task<T>
s. The Result property takes care of the waiting. Approximately:
// untested
Task<List<Employee>> t1 = Task.Factory.StartNew(() => Method1());
Task<List<Employee>> t2 = Task.Factory.StartNew(() => Method2());
var result = t1.Result.Concat(t2.Result);
How can I run both of these methods 'at the same time' in .NET 4.5?
Here is what you may want to do:
public async Task<PewPew> SomeMethod(Foo foo)
{
// get the stuff on another thread
var cTask = Task.Run(() => GetAllTheCats(foo));
var fTask = Task.Run(() => GetAllTheFood(foo));
var cats = await cTask;
var food = await fTask;
return new PewPew
{
Cats = cats,
Food = food
};
}
public IList<Cat> GetAllTheCats(Foo foo)
{
// Do stuff, like hit the Db, spin around, dance, jump, etc...
// It all takes some time.
return cats;
}
public IList<Food> GetAllTheFood(Foo foo)
{
// Do more stuff, like hit the Db, nom nom noms...
// It all takes some time.
return food;
}
There are two things you need to understand here:
What is diff between this:
var cats = await cTask;
var food = await fTask;
And this:
Task.WaitAll(new [] {cTask, fTask});
Both will give you similar result in the sense let the 2 async
tasks finish and then return new PewPew
- however, difference is that Task.WaitAll()
will block the current thread (if that is UI thread, then UI will freeze). instead, await
will break down the SomeMethod
say in a state machine, and return from the SomeMethod
to its caller as it encounters await
keyword. It will not block the thread. The Code below await
will be scheduled to run when async
task is over.
You could also do this:
var cats = await Task.Run(() => GetAllTheCats(foo));
var food = await Task.Run(() => GetAllTheFood(foo));
However, this will not start the async
tasks simultaneously. Second task will start after the first is over. This is because how the await
keyword works.
EDIT: How to use SomeMethod
- somewhere at the start of the call tree, you have to use Wait()
or Result
property - OR - you have to await
from async void
.
Generally, async void
would be an event handler:
public async void OnSomeEvent(object sender, EventArgs ez)
{
Foo f = GetFoo();
PewPew p = await SomeMethod(f);
}
If not then use Result
property.
public Foo2 NonAsyncNonVoidMethod()
{
Foo f = GetFoo();
PewPew p = SomeMethod(f).Result; //But be aware that Result will block thread
return GetFoo2(p);
}
Run 3 Tasks at a time all the time
Only 3 Max at any given time.
The normal way of doing asynchronous concurrency (terminology note: not parallelism) is to use SemaphoreSlim
:
var throttler = new SemaphoreSlim(3);
var task1 = Throttled(m1.FetchAsync);
var task2 = Throttled(m2.FetchAsync);
var task3 = Throttled(m3.FetchAsync);
var task4 = Throttled(m4.FetchAsync);
var task5 = Throttled(m5.FetchAsync);
var task6 = Throttled(m6.FetchAsync);
await Task.WhenAll(tasks);
async Task<T> Throttled<T>(Func<Task<T>> operation)
{
await throttler.WaitAsync();
try { return await operation(); }
finally { throttler.Release(); }
}
Running async methods in parallel
Is there a better to run async methods in parallel, or are tasks a good approach?
Yes, the "best" approach is to utilize the Task.WhenAll
method. However, your second approach should have ran in parallel. I have created a .NET Fiddle, this should help shed some light. Your second approach should actually be running in parallel. My fiddle proves this!
Consider the following:
public Task<Thing[]> GetThingsAsync()
{
var first = GetExpensiveThingAsync();
var second = GetExpensiveThingAsync();
return Task.WhenAll(first, second);
}
Note
It is preferred to use the "Async" suffix, instead of GetThings
and GetExpensiveThing
- we should have GetThingsAsync
and GetExpensiveThingAsync
respectively - source.
Add and remove Parallel.Invoke actions during runtime
You should use Microsoft's Reactive Framework (aka Rx) - NuGet System.Reactive
and add using System.Reactive.Linq;
- then all of your ugly code becomes this:
IObservable<MobileEquipment> query =
from detectedDevicesList in Observable.FromAsync(() => GetConnectedDevices.getAsync())
from detectedDevice in detectedDevicesList.ToObservable()
from mobileEquipment in Observable.FromAsync(() => new MakePhoneCall().call(detectedDevice, listBoxLog))
select mobileEquipment;
The full method now correctly returns Task<String>
, rather than Task<Task<String>>
.
Here it is:
public async Task<String> callWithEveryConnectedDevice(ListBox listBoxLog, Boolean sendAlarms)
{
String TEST_CALLS_COMPLETED = "All test calls completed.";
String TEST_CALLS_FAILED = "One or more test cals failed";
IObservable<MobileEquipment> query =
from detectedDevicesList in Observable.FromAsync(() => GetConnectedDevices.getAsync())
from detectedDevice in detectedDevicesList.ToObservable()
from mobileEquipment in Observable.FromAsync(() => new MakePhoneCall().call(detectedDevice, listBoxLog))
select mobileEquipment;
IList<MobileEquipment> results = await query.ToList();
if (results.Count == 0)
{
UpdateGui.listboxAddItem(listBoxLog, "No devices are connected.", true);
return TEST_CALLS_FAILED;
}
foreach (MobileEquipment mobileEquipment in results)
{
UpdateGui.listboxAddItem(listBoxLog, "Test call result for " + mobileEquipment.serial + " " + mobileEquipment.operador + ": " + mobileEquipment.callSuccess, true);
if (!mobileEquipment.callSuccess && sendAlarms)
{
await SendEmail.sendAlarmEmailsAsync(libreta, asunto, mensaje);
}
}
UpdateGui.listboxAddItem(listBoxLog, TEST_CALLS_COMPLETED, true);
return TEST_CALLS_COMPLETED;
}
How to call same method n times using tasks to run in parallel in c#?
Parallel.For already gives you the necessary marshalling for this sort of task.
const int n = 5; // No more than "n threads"
Parallel.For(0, SomeNumberList.Count, new ParallelOptions{MaxDegreeOfParallelism = n}, i =>
{
DoSomeWork(i);
}
There is another overload which gives you ParallelLoopState if you need to handle exceptions or break calls based on what is happening in concurrent executions.
Related Topics
How to Prevent an Exception in a Background Thread from Terminating an Application
How to Create "Embedded" SQL 2008 Database File If It Doesn't Exist
Combining Datatemplates at Runtime
Rsa Encryption, Getting Bad Length
Binding Combobox Selecteditem Using Mvvm
How to Debug into My Nuget Package Deployed from Teamcity
C# Code for Association, Aggregation, Composition
Save Detached Entity in Entity Framework 6
How to Bind an Enum to a Dropdownlist Control in ASP.NET
How to Get the List of All Printers in Computer
Make a Specific Column Only Accept Numeric Value in Datagridview in Keypress Event
Best Practices: Throwing Exceptions from Properties
Should the Repository Layer Return Data-Transfer-Objects (Dto)
Write Device Platform Specific Code in Xamarin.Forms
How to Add Code Outside the Scope of Main When Using C# 9 Top Level Statements