c# - 在异步方法中省略 async 和 await
问题描述
一个快速的问题;阅读这篇文章:http: //blog.stephencleary.com/2016/12/eliding-async-await.html
它通常告诉我,使用 async/await。已经在这样做了。但是,他还说您在代理任务时不必使用异步部分。
// Simple passthrough to next layer: elide.
Task<string> PassthroughAsync(int x) => _service.DoSomethingPrettyAsync(x);
// Simple overloads for a method: elide.
async Task<string> DoSomethingPrettyAsync(CancellationToken cancellationToken)
{
... // Core implementation, using await.
}
为什么在通过时不应该使用 async/await?这不是不太方便吗,这甚至有意义吗?
有什么想法吗?
解决方案
为什么在通过时不应该使用 async/await?
因为在你输入的那一刻await
,编译器添加了大量的实现胶水,对你完全没有任何作用——调用者已经可以等待被代理的任务。
如果我添加类似您的内容PassthroughAsync
,但使用async
/ await
:
async Task<string> AwaitedAsync(int x) => await DoSomethingPrettyAsync(x);
然后我们可以通过编译和反编译IL看到巨大但完全冗余的代码:
[AsyncStateMachine(typeof(<AwaitedAsync>d__1))]
private Task<string> AwaitedAsync(int x)
{
<AwaitedAsync>d__1 <AwaitedAsync>d__ = default(<AwaitedAsync>d__1);
<AwaitedAsync>d__.<>4__this = this;
<AwaitedAsync>d__.x = x;
<AwaitedAsync>d__.<>t__builder = AsyncTaskMethodBuilder<string>.Create();
<AwaitedAsync>d__.<>1__state = -1;
AsyncTaskMethodBuilder<string> <>t__builder = <AwaitedAsync>d__.<>t__builder;
<>t__builder.Start(ref <AwaitedAsync>d__);
return <AwaitedAsync>d__.<>t__builder.Task;
}
[StructLayout(LayoutKind.Auto)]
[CompilerGenerated]
private struct <AwaitedAsync>d__1 : IAsyncStateMachine
{
public int <>1__state;
public AsyncTaskMethodBuilder<string> <>t__builder;
public C <>4__this;
public int x;
private TaskAwaiter<string> <>u__1;
private void MoveNext()
{
int num = <>1__state;
C c = <>4__this;
string result;
try
{
TaskAwaiter<string> 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<string>);
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<string> PassthroughAsync(int x)
{
return DoSomethingPrettyAsync(x);
}
除了绕过大量的struct
初始化和方法调用之外,如果它实际上是异步的,可能会在堆上“装箱”(在已经同步完成的情况下它不会“装箱”),这PassthroughAsync
也将是一个很棒的JIT 内联的候选者,因此在实际的 CPU 操作码中,PassthroughAsync
可能甚至不存在。
推荐阅读
- python - 如何防止过拟合
- angular-material - 将 cdk Overlay 定位在鼠标位置
- javascript - React 渲染箭头函数性能
- php - WooCommerce 根据产品类别替换购物车/结帐中的“延期交货可用”
- python - Python Netmiko 获取主机名
- postgresql - 使用 postgres 函数创建视图
- postgresql - 查询返回语句 - PostgreSQL
- android - 为什么它在 Retrofit 中返回空值?
- python - 如何摆脱 ConfigParser 未定义错误?
- python - 二维数组到数据框列中的行