有时我会使用一组任务,为了确保它们都被等待,我采用以下方法:
public async Task ReleaseAsync(params Task[] TaskArray)
{
var tasks = new HashSet<Task>(TaskArray);
while (tasks.Any()) tasks.Remove(await Task.WhenAny(tasks));
}
然后像这样调用它:
await ReleaseAsync(task1, task2, task3);
//or
await ReleaseAsync(tasks.ToArray());
然而,最近我注意到了一些奇怪的行为,并试图查看ReleaseAsync方法是否存在问题。我设法将其缩小到这个简单的演示中,如果您包括System.Threading.Tasks
,则可以在linqpad中运行。稍加修改后,它也可以在控制台应用程序或asp.net mvc控制器中运行。
async void Main()
{
Task[] TaskArray = new Task[]{run()};
var tasks = new HashSet<Task>(TaskArray);
while (tasks.Any<Task>()) tasks.Remove(await Task.WhenAny(tasks));
}
public async Task<int> run()
{
return await Task.Run(() => {
Console.WriteLine("started");
throw new Exception("broke");
Console.WriteLine("complete");
return 5;
});
}
我不理解的是为什么异常从未出现在任何地方。我本来以为如果等待异常的任务,它就会抛出异常。通过将while循环替换为简单的for each,我确认了这一点:
foreach( var task in TaskArray )
{
await task;//this will throw the exception properly
}
我的问题是,为什么这个例子没有正确地抛出异常(它从未在任何地方显示)。
Task.WhenAll
的原因是什么? - Paulo Morgado