A cleaner template for running tasks and getting their return values
I'm doing some asynchronous work and can't help but feel like I'm running out of a really ugly design, and I'm wondering how and how this can be rewritten to something that "feels better".
var tasks = new List<Task>();
var t1 = new Task<Guid>(() => DoSomeStuff<Xyz>(dtx, e1, M1));
var t2 = new Task<Guid>(() => DoSomeStuff<Qrs>(dtx, e2, M2));
var t3 = new Task<Guid>(() => DoSomeStuff<Abc>(dtx, e3, M3));
tasks.Add(t1);
tasks.Add(t2);
tasks.Add(t3);
tasks.ForEach(x => x.Start());
Task.WaitAll(tasks.ToArray<Task>());
returnDto.t1value = t1.Result;
returnDto.t2value = t2.Result;
returnDto.t3value = t3.Result;
The variable names have been changed for brevity; in fact, there are many more tasks. Tasks can run independently, but they all need to be completed before we can proceed.
DoSomeStuff
as follows:
private Guid DoSomeStuff<T>(DependentTransaction dtx, T thing, Func<T, Guid> method)
source to share
It would be much easier to use async-await
to wait asynchronously, Task.WhenAll
to wait for multiple tasks and get their results, and Task.Run
to run DoSomeStuff
in parallel:
Guid[] results = await Task.WhenAll(
Task.Run(() => DoSomeStuff<Xyz>(dtx, e1, M1)),
Task.Run(() => DoSomeStuff<Qrs>(dtx, e2, M2)),
Task.Run(() => DoSomeStuff<Abc>(dtx, e3, M3)));
source to share
I am doing some asynchronous work
It is important to distinguish between asynchronous and parallel work. Asynchronous work is usually based on I / O, while parallel work uses multiple threads for CPU bound code.
If your work is asynchronous, then there should be an asynchronous API that you can use to do DoSomeStuff
in a method async
. Once this is done, it is relatively easy to do parallel asynchronous work:
Guid[] results = await Task.WhenAll(DoSomeStuffAsync<Xyz>(dtx, e1, M1),
DoSomeStuffAsync<Qrs>(dtx, e2, M2), DoSomeStuffAsync<Abc>(dtx, e3, M3));
However, if your work is parallel it is better to use a class Parallel
(or Parallel LINQ):
Guid[] results = new Guid[3];
Parallel.Invoke(() => { results[0] = DoSomeStuff<Xyz>(dtx, e1, M1); },
() => { results[1] = DoSomeStuff<Qrs>(dtx, e2, M2); },
() => { results[2] = DoSomeStuff<Abc>(dtx, e3, M3); });
source to share