嵌套async / await方法

时间:2012-08-02 14:17:47

标签: c# async-await c#-5.0

我正在编写一个包含第三方Web服务调用的库,并且正在尝试使库使用新的async / await功能。在以下示例中,async / await关键字的正确用法是什么?

public class MyApi
{
    public Task<ApiResult> DoSomethingAsync()
    {
        return this.DoSomethingCore();
    }

    public async Task<ApiResult> DoSomethingElseAsync()
    {
        return await this.DoSomethingCore();
    }

    private async Task<ApiResult> DoSomethingCore()
    {
        var httpClient = new HttpClient();
        var httpResponseMessage = await httpClient.GetAsync("some url");
        var rawResultText = await httpResponseMessage.Content.ReadAsStringAsync();
        return new ApiResult(rawResultText);        
    }
}

要允许我的调用者等待DoSomethingAsync方法,该方法是否还要添加async和await关键字?或者它是否正常,因为它返回一个任务?这种嵌套有更好的模式吗?

我认为DoSomethingAsync方法是正确的方法,这是正确的吗?我相信DoSomethingElseAsync在构建库时似乎是错误的方法。

2 个答案:

答案 0 :(得分:11)

任何Task都可以等待,无论它来自哪里。

我不确定为什么DoSomethingAsync只调用DoSomethingCore,因为DoSomethingAsync可以很容易async并使用await

还有general rule您应该在库方法中使用ConfigureAwait(false)

修改:如果您不需要使用await,请不要使用方法asyncasync将增加一些开销(检查Channel Tof的Stephen Toub的Async Performance视频的Zen)。如果您可以返回Task(例如DoSomethingAsync),那么就这样做。

答案 1 :(得分:2)

下面的公式是有效的,但可能会导致额外的开销(由于有额外的async / await方法的辅助回调。)

public async Task<ApiResult> DoSomethingElseAsync()
{
    return await this.DoSomethingCore();
}

直接返回任务更简单,因为您始终可以在其他地方等待该任务,而无需将该方法实现为“异步”。 Async / await与使用'yield return'非常相似;它有一些编译器魔法来实现'让步',但枚举本身并不关心你如何实现它。同样,“等待”电话并不关心等待的工作方式,只要它是等待的。