Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Await Task.WhenAll() inside task not awaiting

My problem is that when a Task has a Task.WhenAll() call (running other Tasks) the line of WhenAll() makes the consuming code continue execution, unlike what I would expect. So the following code outputs "finished" immediately when the Task.WhenAll() is hit, not after all the tasks in its argument are finished.

    // Just a simple async method
    public Task DoWorkAsync()
    {
        return Task.Factory.StartNew(
            () =>
            {
                // Working
            });
    }

    // This one used the previous one with Task.WhenAll()
    public Task DoLoadsOfWorkAsync()
    {
        return Task.Factory.StartNew(
            async () =>
            {
                // Working
                // This line makes the task return immediately
                await Task.WhenAll(DoWorkAsync(), DoWorkAsync());
                // Working
            });
    }

    // Consuming code
    await DoLoadsOfWorkAsync();
    Console.WriteLine("finished");

I'd expect the WriteLine() to be called when the last line of DoLoadsOfWorkAsync() is executed.

What am I doing wrong? Thanks in advance.

like image 283
Piedone Avatar asked Nov 17 '12 15:11

Piedone


People also ask

Does task WhenAll start the tasks?

WhenAll starts both Tasks at the same time and executes them in parallel, the outcome is that instead of taking 3 seconds to run the program it just takes 2 seconds, that's a huge performance enhancement!

How does task WhenAll work?

WhenAll method to a collection of tasks. The application of WhenAll returns a single task that isn't complete until every task in the collection is completed. The tasks appear to run in parallel, but no additional threads are created. The tasks can complete in any order.

What happens if you don't await a task C#?

If you don't await the task or explicitly check for exceptions, the exception is lost. If you await the task, its exception is rethrown. As a best practice, you should always await the call. By default, this message is a warning.

What is the difference between task WaitAll and task WhenAll?

The Task. WaitAll blocks the current thread until all other tasks have completed execution. The Task. WhenAll method is used to create a task that will complete if and only if all the other tasks have completed.


1 Answers

Task.WhenAll returns a new Task immediately, it does not block. The returned task will complete when all tasks passed to WhenAll have completed.

It is an asynchronous equivalent to Task.WaitAll, and this is the method to use if you want to block.

However you have another problem. Using Task.Factory.StartNew and passing an async delegate seems to lead to a type of Task<Task> where the outer task completes when the inner task starts to execute (rather than when it has completed).

Using the newer Task.Run avoids this.

like image 153
Richard Avatar answered Oct 04 '22 06:10

Richard