经过几个小时的努力,我在我的应用程序中发现了一个错误。我认为下面的两个函数具有相同的行为,但事实证明它们并非如此。
谁能告诉我幕后到底发生了什么,以及为什么他们的行为方式不同?
public async Task MyFunction1(IEnumerable<Task> tasks){
await Task.WhenAll(tasks);
Console.WriteLine("all done"); // happens AFTER all tasks are finished
}
public async Task MyFunction2(IEnumerable<Task> tasks){
foreach(var task in tasks){
await task;
}
Console.WriteLine("all done"); // happens BEFORE all tasks are finished
}
它们的功能相同如果所有任务成功完成.
如果你使用WhenAll
并且任何项目失败,在所有项目完成之前它仍然不会完成,并且它将代表一个AggregatException
包裹着all错误来自all tasks.
If you await
每一个一旦命中就会完成any失败的项目,它将代表一个例外one错误,而不是任何其他错误。
两者的区别还在于WhenAll
将会具体化整个IEnumerable
就在开始时,在向其他项目添加任何延续之前。如果IEnumerable
表示已经存在和已启动的任务的集合,那么这是不相关的,但是如果迭代可枚举的行为创建和/或启动任务,那么在开始时具体化序列将并行运行它们,并在之前等待每个任务获取下一个任务将按顺序执行它们。下面是一个IEnumerable
你可以传入它的行为,就像我在这里描述的那样:
public static IEnumerable<Task> TaskGeneratorSequence()
{
for(int i = 0; i < 10; i++)
yield return Task.Delay(TimeSpan.FromSeconds(2);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)