【问题标题】:Can we turn async methods into expression body?我们可以把异步方法变成表达式体吗?
【发布时间】:2015-10-10 12:51:27
【问题描述】:

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

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

他说不建议在上面的代码中使用async和await关键字:

编译器正在执行一些繁重的工作来实现异步 此方法的状态机。由于方法的结构, 额外的工作并没有真正完成太多。它正在创建一个状态 机器来包装一个任务,该任务只是解开从一个返回的任务 不同的方法。 他建议我们应该编写不带 async 和 await 的代码:

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

我想了解更多相关信息。

【问题讨论】:

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


    【解决方案1】:

    让我们看看作者在说什么。当您将方法标记为 async 时,编译器会代表您生成一个状态机,以便让异步执行方式“感觉”它正在同步执行。

    当你写作时:

    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;
    }
    

    由于您使用的是表达式主体方法,因此您实际上只有一个方法的衬里。您一般什么时候await 做某事?当您想要操作异步方法的返回值时。对于单线,情况绝不会如此。这意味着您可以在调用级别保存状态机生成,并且只让那些想要准确地await 结果的人在调用者堆栈中更高到您方法上的await。这将有效地将您的方法转换为如下所示:

    public Task<string> ReadFromWeb()
    {
        return this.RunWebRequest();
    }
    

    这为您节省了编译器分配的相当已经很苗条的状态机struct,这在您创建 EBM 时实际上是相当多余的。

    【讨论】:

      【解决方案2】:

      使方法异步允许您在其中使用等待。您真的不需要等待,因为您没有使用返回值,并且在该操作完成后您没有做任何事情。在这种情况下,您可以直接返回任务。这样,您的调用者就可以等待内部异步方法,而不会产生中间方法的开销。

      这避免了使 ReadFromWeb 成为异步方法的工作。这没什么大不了的,但在这种情况下,你所拥有的只是一次调用,这样做是无害的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-03-18
        • 2014-08-06
        • 2018-09-17
        • 1970-01-01
        • 1970-01-01
        • 2016-02-23
        • 2014-05-19
        • 1970-01-01
        相关资源
        最近更新 更多