我们可以将异步方法转换为表达式主体吗?

时间:2015-10-10 12:51:27

标签: c# asynchronous async-await c#-6.0

我正在阅读关于C#6.0中表达身体成员的this文章,作者演示了这段代码:

public async Task<string> ReadFromWeb() => await RunWebRequest();

他说不建议在上面的代码中使用asyncawait个关键字:

  

编译器正在执行一些繁重的工作以实现异步   这种方法的状态机。由于该方法的结构,   额外的工作并没有真正实现。它创造了一个国家   机器包装一个简单地解包从一个任务返回的任务的任务   不同的方法。   他提议我们应该编写没有异步的代码并等待:

public Task<string> ReadFromWebSimple() => RunWebRequest();

我想了解更多相关信息。

2 个答案:

答案 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成为异步方法的工作。这不是一个大问题,但在这种情况下你所拥有的只是一次调用,这是非常无害的。