Reputation: 602
I'm implementing some asynchronous work and cant help but feel I'm ending up with a really ugly construction and I'm wondering if and how this could 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;
Variable names have been changed for brevity, there are actually a lot more tasks. Tasks can all run independently, but all have to be completed before we can continue.
DoSomeStuff
looks like this:
private Guid DoSomeStuff<T>(DependentTransaction dtx, T thing, Func<T, Guid> method)
Upvotes: 3
Views: 162
Reputation: 456477
I'm implementing some asynchronous work
It's important to distinguish between asynchronous and parallel work. Asynchronous work is usually I/O-based, while parallel work uses multiple threads for CPU-bound code.
If your work is asynchronous, then there should be an asynchronous API you can use to make DoSomeStuff
into an async
method. Once that is done, it's relatively easy to do concurrent 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, then it's best to use the Parallel
class (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); });
Upvotes: 1
Reputation: 116548
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)));
Upvotes: 5