Coder Perfect

Performing numerous async operations while waiting for them to finish

Problem

In a console application, I need to start numerous async jobs and wait for them all to finish before proceeding.

There are numerous articles available, but the more I read, the more perplexed I become. I’ve studied and comprehended the Task library’s essential principles, yet there’s plainly something lacking.

I realize that tasks can be chained such that one starts after the other (which is pretty much the situation in all of the articles I’ve read), but I want all of my Tasks to run at the same time, and I want to know when they’re all done.

What is the simplest way to implement this scenario?

Asked by Daniel Minnaar

Solution #1

Both answers failed to mention the pending Task. WhenAll:

var task1 = DoWorkAsync();
var task2 = DoMoreWorkAsync();

await Task.WhenAll(task1, task2);

The key distinction between Task and Task. Task and WaitAll The difference between When and WhenAll is that the former will block (equivalent to using Wait on a single job), whereas the latter will not and can be awaited, returning control to the caller once all tasks have completed.

Exception handling is also different:

Task.WaitAll:

Task.WhenAll:

Answered by Yuval Itzchakov

Solution #2

You could create many tasks like:

List<Task> TaskList = new List<Task>();
foreach(...)
{
   var LastTask = new Task(SomeFunction);
   LastTask.Start();
   TaskList.Add(LastTask);
}

Task.WaitAll(TaskList.ToArray());

Answered by Virus

Solution #3

WhenAll returns an awaitable Task, while WaitAll has no return type and blocks further function execution in the same way that Thread does. Sleep until you’ve completed, canceled, or faulted all of your tasks.

Example

var tasks = new Task[] {
    TaskOperationOne(),
    TaskOperationTwo()
};

Task.WaitAll(tasks);
// or
await Task.WhenAll(tasks);

You can use this response for inspiration if you want to execute the jobs in a specific order.

Answered by NtFreX

Solution #4

The following extension method is the best solution I’ve seen:

public static Task ForEachAsync<T>(this IEnumerable<T> sequence, Func<T, Task> action) {
    return Task.WhenAll(sequence.Select(action));
}

It’s referred to as:

await sequence.ForEachAsync(item => item.SomethingAsync(blah));

Alternatively, use an async lambda:

await sequence.ForEachAsync(async item => {
    var more = await GetMoreAsync(item);
    await more.FrobbleAsync();
});

Answered by me22

Solution #5

Another answer…but I generally find myself in a situation where I need to load data at the same time and store it in variables, such as:

var cats = new List<Cat>();
var dog = new Dog();

var loadDataTasks = new Task[]
{
    Task.Run(async () => cats = await LoadCatsAsync()),
    Task.Run(async () => dog = await LoadDogAsync())
};

try
{
    await Task.WhenAll(loadDataTasks);
}
catch (Exception ex)
{
    // handle exception
}

Answered by Yehor Hromadskyi

Post is based on https://stackoverflow.com/questions/25009437/running-multiple-async-tasks-and-waiting-for-them-all-to-complete