在异步方法中避免异步和等待

一个简单的问题; 阅读本文: http : //blog.stephencleary.com/2016/12/eliding-async-await.html

它通常告诉我,使用async / await。 已经这样做了。 但是,他也说你在代理任务时不必使用异步部分。

// Simple passthrough to next layer: elide. Task PassthroughAsync(int x) => _service.DoSomethingPrettyAsync(x); // Simple overloads for a method: elide. async Task DoSomethingPrettyAsync(CancellationToken cancellationToken) { ... // Core implementation, using await. } 

为什么在通过时不应该使用async / await? 这不是那么方便,这甚至有意义吗?

任何想法?

为什么在通过时不应该使用async / await?

因为你输入await的那一刻,编译器会添加大量的实现粘合剂,它对你毫无帮助 – 调用者已经可以等待代理任务了。

如果我添加类似你的PassthroughAsync ,但使用async / await

 async Task AwaitedAsync(int x) => await DoSomethingPrettyAsync(x); 

那么我们可以通过编译和反编译IL来看到巨大但完全冗余的代码:

 [AsyncStateMachine(typeof(d__1))] private Task AwaitedAsync(int x) { d__1 d__ = default(d__1); d__.<>4__this = this; d__.x = x; d__.<>t__builder = AsyncTaskMethodBuilder.Create(); d__.<>1__state = -1; AsyncTaskMethodBuilder <>t__builder = d__.<>t__builder; <>t__builder.Start(ref d__); return d__.<>t__builder.Task; } [StructLayout(LayoutKind.Auto)] [CompilerGenerated] private struct d__1 : IAsyncStateMachine { public int <>1__state; public AsyncTaskMethodBuilder <>t__builder; public C <>4__this; public int x; private TaskAwaiter <>u__1; private void MoveNext() { int num = <>1__state; C c = <>4__this; string result; try { TaskAwaiter awaiter; if (num != 0) { awaiter = c.DoSomethingPrettyAsync(x).GetAwaiter(); if (!awaiter.IsCompleted) { num = (<>1__state = 0); <>u__1 = awaiter; <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this); return; } } else { awaiter = <>u__1; <>u__1 = default(TaskAwaiter); num = (<>1__state = -1); } result = awaiter.GetResult(); } catch (Exception exception) { <>1__state = -2; <>t__builder.SetException(exception); return; } <>1__state = -2; <>t__builder.SetResult(result); } void IAsyncStateMachine.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext this.MoveNext(); } [DebuggerHidden] private void SetStateMachine(IAsyncStateMachine stateMachine) { <>t__builder.SetStateMachine(stateMachine); } void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { //ILSpy generated this explicit interface implementation from .override directive in SetStateMachine this.SetStateMachine(stateMachine); } } 

现在与非async passthru编译的对比:

 private Task PassthroughAsync(int x) { return DoSomethingPrettyAsync(x); } 

除了绕过大量的struct初始化和方法调用之外,如果它实际上是异步的(在已完成的同步情况下它不是“盒子”),那么堆上可能的“盒子”,这个PassthroughAsync也将是JIT内联的一个很好的候选者,所以在实际的CPU操作码中PassthroughAsync可能甚至不存在。