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)

      

+3


source to share


2 answers


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

      

+5


source


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

      

+1


source







All Articles