我正在尝试并行化从集合发出的工作,并等待所有任务的完成。
这基本上是我所拥有的:
public Task<int> DoWorkAsync(int arg){
return Task.Factory.StartNew(()=> {
Thread.Sleep(1000);
return arg*2;
});
}
public async void DoAllWorks(){
ICollection<int> workToDo = GetSomeWorkFromSomewhere();
IEnumerable<Task<int>> tasks = workToDo.Select(i=> DoWorkAsync(i));
int[] results = await Task.WhenAll(tasks);
Debug.Write(results.Sum()); // Never called
}
public void Main(){
DoAllWorks();
// rest of code, which is called
OtherMethods();
}
但是,WhenAll
方法会立即退出,其余代码将运行,即使仍有工作在执行。
如何解决?
您正在使用的async void
只应用于事件处理程序。
使用async void
时,无法等待async
操作完成(同步或异步)。这意味着它会"触发"DoAllWorks
并继续前进,因为它不知道DoAllWorks
何时完成。 await Task.WhenAll(tasks)
DoAllWorks
内部等待得很好,但调用方法已经移动。
在这种情况下,您应该返回一个可以await
或Wait()
的任务,因为Main
无法自行async
。
public void Main()
{
DoAllWorks().Wait();
// rest of code, which is called
OtherMethods();
}
public async Task DoAllWorks()
{
ICollection<int> workToDo = GetSomeWorkFromSomewhere();
IEnumerable<Task<int>> tasks = workToDo.Select(i=> DoWorkAsync(i));
int[] results = await Task.WhenAll(tasks);
Debug.Write(results.Sum());
}
事件处理程序外,不应使用异步 void。如果你返回一个任务,你可以在main方法中等待它await
关键字或类似:
DoAllWorks().Wait();
仅供参考,您不需要使用 Thread.Sleep(1000);
.您可以稍微重写代码以与构造async/await
更一致
return Task.Run(async ()=> {
await Task.Delay(1000);
return arg*2;
});