-2

I have a C# console app that I'm using for experimentation. I have some blocks of code that I know that I want to run 1) Asynchronously 2) in Parallel and 3) Run some shared cleanup code when each block finishes.

I need to run the blocks asynchronously because each one is calling a web service. I need to run each block in parallel for performance reasons and no block is dependent on the other. Finally, I have a significant amount of clean-up and logging code that I want to run when each block finishes. For that reason, this code is shared.

I'm getting stuck in how to do this. Thus far, I've looked the following C# concepts:

1) Tasks - Pros: Good at running code asynchronously Cons: a) I do not see a way to define a task and pass it to a shared method so that I can run my clean up code. b) I do not see a good way to pass parameters to a Task

2) Actions - Pros: a) Can define code blocks inline i.e. var myAction = (Action)(() => { });. b) Can easily pass parameters to the Action. Cons: Doesn't seem to be a way to run actions asynchronously, thus b) Not sure I can run actions in parallel.

As I write this question, it's clear I'm missing something. At first glance, Tasks seem like the correct road to go down. However, I do feel stuck in the fact that

public void RunTaskInParallel(Task task)
{
  var startTime = DateTime.UtcNow;

  // Execute task code

  var executionTime = DateTime.UtcNow.Subtract(startTime);
  // Log the execution time    

  // Execute Clean-up Code
}

How do I run a block of code, asynchronously, in parallel, in a way that allows me to execute some shared clean-up code when all is said and done? I feel like I'm always getting two-of-three requirements, but struggling to get all three.

Thank you for your help!

Some User
  • 5,257
  • 13
  • 51
  • 93

3 Answers3

0

You can create a list of tasks you need to execute in parallel and then asynchronously wait till all tasks are completed with Task.WhenAll static method:

await Task.WhenAll(new []{ RoutineA(), RoutineB()});
Cleanup();

RoutineA and RoutineB can be async functions, returning Task. Please note we do NOT await these calls - so calling thread continues triggering RoutineB after it initiated RoutineA.

Sasha
  • 8,537
  • 4
  • 49
  • 76
0

You can do .WhenAll to run some task in parallel and asynchronously.

for e.g

Task a = AsyncTaskA();
Task b = AsyncTaskB();
Task c = AsyncTaskC();
List<Task> AllTasks = new List<Task>();
AllTasks.Add(a);
AllTasks.Add(b);
AllTasks.Add(c);
// this will run all your tasks async and parallel and also wait until everything is done
await Task.WhenAll(AllTasks);
-1

I would use Task.WaitAll, It would look something like:

         var stopwatch = new Stopwatch();
        stopwatch.Start();

        Action<string> logTime = (label) => Console.WriteLine($"{label}: {stopwatch.Elapsed.Seconds} in Seconds");


        var taskList = new List<Task>();
        taskList.Add(Task.Run(() => { DoWork(); logTime("Task 1");}));
        taskList.Add(Task.Run(() => { DoWork(); logTime("Task 2"); }));
        taskList.Add(Task.Run(() => { DoWork(); logTime("Task 3"); }));
        taskList.Add(Task.Run(() => { DoWork(); logTime("Task 4"); }));
        taskList.Add(Task.Run(() => { DoWork(); logTime("Task 5"); }));
        taskList.Add(Task.Run(() => { DoWork(); logTime("Task 6"); }));
        taskList.Add(Task.Run(() => { DoWork(); logTime("Task 7"); }));
        taskList.Add(Task.Run(() => { DoWork(); logTime("Task 8"); }));

        await Task.Run(()=>Task.WaitAll(taskList.ToArray()));
        stopwatch.Stop();

        var timeRan = stopwatch.Elapsed.Seconds;
        //log time
        logTime("Total Time");
        Console.ReadLine();
3xGuy
  • 2,235
  • 2
  • 29
  • 51