在任务中未等待的情况下使用 Await Task.WhenAll()

5

我的问题是,当一个任务有一个Task.WhenAll()调用(运行其他任务)时,WhenAll()的这一行会使得代码继续执行,而不是像我所期望的那样等待所有参数中的任务都完成后再输出"finished"。因此,下面的代码在Task.WhenAll()被执行时立即输出"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");

我希望当DoLoadsOfWorkAsync()的最后一行被执行时,WriteLine()会被调用。
我错在哪里?提前感谢您的帮助。
1个回答

21

Task.WhenAll 立即返回一个新的 Task,不会阻塞。当传递给 WhenAll 的所有任务都完成时,返回的任务将完成。

它是 Task.WaitAll 的异步等效方法,如果想要阻塞,则使用此方法。

但是您还有另一个问题。使用 Task.Factory.StartNew 并传递一个 async 委托似乎会导致一种 Task<Task> 类型,其中外部任务在内部任务开始执行时就完成了(而不是在其完成时)。

使用更新的 Task.Run 可以避免这种情况。


你做得很好:问题在于Task<Task>,我忽略了它。顺便说一下,我不想让线程阻塞,只是在前面的任务完成后继续执行。这就是为什么我使用Task.WhenAll()而不是wait与async-await结构一起使用。非常感谢你的帮助! - Piedone
如果你想了解 Task.Run 及其作用的好处(以及为什么以及如何实现),请前往这里:http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx - ckozl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接