Await Task.WhenAll() inside task not awaiting

10,927

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.

Share:
10,927
Piedone
Author by

Piedone

Zoltán Lehóczky here, a computer science and engineering student from Hungary. I'm the co-founder of Lombiq Technologies Ltd., a company focused on services related to the Orchard content management framework. See my LinkedIn profile.

Updated on June 05, 2022

Comments

  • Piedone
    Piedone almost 2 years

    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.

  • Piedone
    Piedone over 11 years
    You nailed it: the problem was the Task<Task>, I have overlooked it. BTW I don't want the thread to block, just to continue execution after the previous tasks are finished. That's why I used Task.WhenAll() instead of wait together with the aync-await construct. Thank you very much for your help!
  • ckozl
    ckozl about 11 years
    if you want to read about Task.Run and all its goodness (and why and how it does what it does) go here: blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx