我正在阅读关于C#6.0中表达身体成员的this文章,作者演示了这段代码:
public async Task<string> ReadFromWeb() => await RunWebRequest();
他说不建议在上面的代码中使用async
和await
个关键字:
编译器正在执行一些繁重的工作以实现异步 这种方法的状态机。由于该方法的结构, 额外的工作并没有真正实现。它创造了一个国家 机器包装一个简单地解包从一个任务返回的任务的任务 不同的方法。 他提议我们应该编写没有异步的代码并等待:
public Task<string> ReadFromWebSimple() => RunWebRequest();
我想了解更多相关信息。
答案 0 :(得分:7)
让我们看看作者在谈论什么。当您将方法标记为async
时,编译器会代表您生成一个状态机,以便允许异步执行方式感觉像&#34;它是同步执行的。
当你写:
public async Task<string> ReadFromWeb() => await RunWebRequest();
编译器生成:
[AsyncStateMachine(typeof(C.<RunWebRequest>d__1))]
public Task<string> RunWebRequest()
{
C.<RunWebRequest>d__1 <RunWebRequest>d__;
<RunWebRequest>d__.<>t__builder = AsyncTaskMethodBuilder<string>.Create();
<RunWebRequest>d__.<>1__state = -1;
AsyncTaskMethodBuilder<string> <>t__builder = <RunWebRequest>d__.<>t__builder;
<>t__builder.Start<C.<RunWebRequest>d__1>(ref <RunWebRequest>d__);
return <RunWebRequest>d__.<>t__builder.Task;
}
由于您使用的是Expression Bodied方法,因此您实际上只有一个方法的单线程。你什么时候开始await
什么的?当你想 操纵异步方法的返回值 时。对于单行而言,情况从未如此。这意味着您可以在调用级别保存状态机生成,并且只允许那些想要实际await
结果的人将调度程序堆栈中的结果提高到方法上的await
。这将有效地将您的方法转换为如下所示:
public Task<string> ReadFromWeb()
{
return this.RunWebRequest();
}
这样可以节省编译器分配的已经很小的状态机struct
,这在你创建EBM时实际上是多余的。
答案 1 :(得分:2)
使方法异步允许您在其中使用await。您不需要等待,因为您没有使用返回值,并且在该操作完成后您没有做任何事情。在这种情况下,您可以直接返回任务。这样你的调用者就可以等待内部的异步方法,而不需要中间方法的开销。
这避免了使ReadFromWeb
成为异步方法的工作。这不是一个大问题,但在这种情况下你所拥有的只是一次调用,这是非常无害的。