Task.WaitAll不等待 - 解释

4
以下代码(LINQPad示例)预计创建5个工作任务并等待它们全部完成。
相反,它启动了5个任务,并立即输出"... Done" - 消息。
问题在于Task.Run之后的(Action) - 转换。如果我删除该转换,则一切都按预期工作。
这里发生了什么?对我来说没有任何意义,因为在我看来,此转换是多余的。
void Main()
{
    var tasks = Enumerable.Range(1, 5).Select(x => this.DoWork()).ToArray();

    Console.WriteLine("Waiting ... ");
    Task.WaitAll(tasks);
    Console.WriteLine("... Done");
}

Task DoWork()
{
    return Task.Run(
        (Action)(async () =>
        {
            Console.WriteLine("Task start");
            await Task.Delay(3000);
            Console.WriteLine("Task end");
        }));
}

1
我认为你需要在DoWork中创建的任务的()前删除async。你创建的任务会创建另一个任务,但它不会等待该任务完成并立即返回。 - Lee
1
你代码中的Task.WaitAll()方法没有处理延迟的任务,而是处理了从Task.Run方法返回的任务。也就是说,你没有等待这些任务,而是等待创建内部任务的任务。创建过程瞬间完成,内部任务本身不会阻塞,除非你在其中删除"await"语句,因此等待它们不会有太大的区别。 - Tormod
1个回答

5

我认为,这是因为异步lambda(不带转换)返回了Task,C#编译器选择了接受Func<Task>委托的Task.Run()方法的重载。如果将委托转换为Action,编译器就会选择接受Action的重载,当调用Task.Delay()方法时,DoWork()方法返回的任务就会结束。结果是Task.WaitAll()方法在Task.Delay()任务完成之前就结束了。


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