如何使用Task.WaitAll来等待这两个任务

mic*_*ael 0 c# task-parallel-library

我有以下代码调用2个异步方法并等待结果:

private Task FirstTaskAsync() {
...
}
private Task SecondTaskAsync() {
...
}

private async void Caller() {
   await FirstTaskAsync();
   await SecondTaskAsync();
}
Run Code Online (Sandbox Code Playgroud)

问题是它现在执行并顺序等待每个任务.我想将其更改为Task.WaitAll().这是我的改变:

private async void Caller() {
   var first = FirstTaskAsync();
   var second = SecondTaskAsync();

   Task.WaitAll(first, second);
}
Run Code Online (Sandbox Code Playgroud)

但是当我测试它时,Task.WaitAll()永远不会返回.你能告诉我缺少什么吗?

Sco*_*ain 5

首先,async void除非你正在做一个事件处理程序(我怀疑你是),否则你永远不应该这样做,如果你这样async Task做会让你的问题变得更加明显.

private async Task Caller() {
   await FirstTaskAsync();
   await SecondTaskAsync();
}

//This still will not work...
private async Task Caller() {
   var first = FirstTaskAsync();
   var second = SecondTaskAsync();

   Task.WaitAll(first, second);
}
Run Code Online (Sandbox Code Playgroud)

Task.WaitAll返回void并且你永远不会await在第二种方法中使用,所以你正在同步执行代码并阻塞SynchronizationContext 它会导致你遇到像你看到的死锁.

正确的解决方案不是阻止而是使用Task.WhenAll返回一个Task本身,它允许你删除async关键字并返回结果

private Task Caller() {
   var first = FirstTaskAsync();
   var second = SecondTaskAsync();

   return Task.WhenAll(first, second);
}
Run Code Online (Sandbox Code Playgroud)

但是,如果Caller()确实是事件处理程序,您也可以执行async void并等待结果.

private async void Caller() { //This should only be done if this is a event handler.
   var first = FirstTaskAsync();
   var second = SecondTaskAsync();

   await Task.WhenAll(first, second);
}
Run Code Online (Sandbox Code Playgroud)