为什么我应该更喜欢单个“等待Task.WhenAll”多个等待?
如果我不关心任务完成的顺序,只需要它们全部完成,我还应该使用await Task.WhenAll
而不是多个await
? 例如DoWord2
是DoWord2
的首选方法(为什么?):
using System; using System.Threading.Tasks; namespace ConsoleApp { class Program { static async Task<string> DoTaskAsync(string name, int timeout) { var start = DateTime.Now; Console.WriteLine("Enter {0}, {1}", name, timeout); await Task.Delay(timeout); Console.WriteLine("Exit {0}, {1}", name, (DateTime.Now - start).TotalMilliseconds); return name; } static async Task DoWork1() { var t1 = DoTaskAsync("t1.1", 3000); var t2 = DoTaskAsync("t1.2", 2000); var t3 = DoTaskAsync("t1.3", 1000); await t1; await t2; await t3; Console.WriteLine("DoWork1 results: {0}", String.Join(", ", t1.Result, t2.Result, t3.Result)); } static async Task DoWork2() { var t1 = DoTaskAsync("t2.1", 3000); var t2 = DoTaskAsync("t2.2", 2000); var t3 = DoTaskAsync("t2.3", 1000); await Task.WhenAll(t1, t2, t3); Console.WriteLine("DoWork2 results: {0}", String.Join(", ", t1.Result, t2.Result, t3.Result)); } static void Main(string[] args) { Task.WhenAll(DoWork1(), DoWork2()).Wait(); } } }
是的,使用WhenAll
因为它一次传播所有的错误。 有了多个等待,你会失去如果之前的等待投掷错误。
另一个重要的区别是,WhenAll将等待所有任务完成。 在第一个例外情况下,一连串的await
将中止等待 ,但是不等待执行的任务仍在继续。 这会导致意外的并发。
我认为这也使阅读代码更容易,因为你想要的语义直接logging在代码中。
我的理解是,更喜欢Task.WhenAll
多个await
s的主要原因是性能/任务“搅动”: DoWork1
方法做这样的事情:
- 从给定的上下文开始
- 保存上下文
- 等待t1
- 恢复原来的上下文
- 保存上下文
- 等待t2
- 恢复原来的上下文
- 保存上下文
- 等待t3
- 恢复原来的上下文
相比之下, DoWork2
做到这一点:
- 从给定的上下文开始
- 保存上下文
- 等待所有的t1,t2和t3
- 恢复原来的上下文
当然,对于你的具体情况来说,这是一个足够大的交易,是“上下文相关的”(赦免双关语)。
一个asynchronous方法被实现为一个状态机。 编写方法是不可能被编译进状态机的,这通常被称为快速asynchronous方法。 这些可以这样实现:
public Task DoSomethingAsync() { return DoSomethingElseAsync(); }
当使用Task.WhenAll
,可以保持这个快速代码,同时仍然确保调用者能够等待所有任务完成,例如:
public Task DoSomethingAsync() { var t1 = DoTaskAsync("t2.1", 3000); var t2 = DoTaskAsync("t2.2", 2000); var t3 = DoTaskAsync("t2.3", 1000); return Task.WhenAll(t1, t2, t3); }
- C#:从System.Typedynamic分析
- 访问同一class级另一个对象的私人领域
- ASP.Net MVCredirect到一个不同的视图
- 我如何允许assembly(unit testing)来访问另一个assembly的内部属性?
- entity framework4与NHibernate
- 等到一个过程结束
- AssemblyVersion,AssemblyFileVersion和AssemblyInformationalVersion之间有什么区别?
- 例外:“不支持URI格式”
- 传递到字典中的模型项目types为“mvc.Models.ModelA”,但是此字典需要“mvc.Models.ModelB”types的模型项目