I need to run multiple async tasks in a console application, and wait for them all to complete before further processing.

There's many articles out there, but I seem to get more confused the more I read. I've read and understand the basic principles of the Task library, but I'm clearly missing a link somewhere.

I understand that it's possible to chain tasks so that they start after another completes (which is pretty much the scenario for all the articles I've read), but I want all my Tasks running at the same time, and I want to know once they're all completed.

8 Answers
8

The main difference between Task.WaitAll and Task.WhenAll is that the former will block (similar to using Wait on a single task) while the latter will not and can be awaited, yielding control back to the caller until all tasks finish.

More so, exception handling differs:

Task.WaitAll:

At least one of the Task instances was canceled -or- an exception was thrown during the execution of at least one of the Task instances. If a task was canceled, the AggregateException contains an OperationCanceledException in its InnerExceptions collection.

Task.WhenAll:

If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state, where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.

If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.

If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion state before it's returned to the caller.

Is it possible to start multiple new threads, at the same time, using the await keyword rather than .Start() ?
– Matt WSep 1 '15 at 6:36

1

@MattW No, when you use await, it would wait for it to complete. In this case you would not be able to create a multi-threaded environment. This is the reason that all the tasks are waited at the end of the loop.
– VirusSep 1 '15 at 8:40

4

Downvote for future readers since it isn't made clear that this is a blocking call.
– JRoughanOct 11 '16 at 1:56

See the accepted answer for reasons why not to do this.
– EL MOJOSep 6 '17 at 16:30

You can use WhenAll which will return an awaitable Task or WaitAll which has no return type and will block further code execution simular to Thread.Sleep until all tasks are completed, canceled or faulted.

and don't forget to check the previous Task instance in each ContinueWith as it might be faulted.

For the parallel manner
The most simple method I came across: Parallel.Invoke
Otherwise there's Task.WaitAll or you can even use WaitHandles for doing a countdown to zero actions left (wait, there's a new class: CountdownEvent), or ...

Appreciate the answer, but your suggestions could have been explained a little more.
– Daniel MinnaarJul 29 '14 at 6:56

@drminnaar which other explanation beside the links to msdn with examples do you need? you didn't even click on the links, did you?
– Andreas NiedermairJul 29 '14 at 7:08

4

I clicked on the links, and I read the content. I was going for the Invoke, but there were a lot of If's and But's about whether it runs asynchronously or not. You were editing your answer continuously. The WaitAll link you posted was perfect, but I went for the answer that demonstrated the same functionality in a quicker and easier to read way. Don't take offense, your answer still provides good alternatives to other approaches.
– Daniel MinnaarJul 29 '14 at 8:24