19

我正在编写一个包装第三方 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 在构建库时似乎是错误的方法。

4

2 回答 2

16

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

我不知道为什么DoSomethingAsync只是打电话DoSomethingCore,因为DoSomethingAsync可以很容易地async使用await

还有一个你应该在库方法中使用的一般规则。ConfigureAwait(false)

编辑:如果您不需要使用await,则不要制作该方法asyncasync将增加一些开销(查看 Channel9 以获取 Stephen Toub 的 Zen of Async Performance 视频)。如果你可以只返回一个Task(like DoSomethingAsync),那么就这样做。

于 2012-08-02T14:24:00.523 回答
3

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

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

直接返回任务更简单,因为您始终可以在其他地方等待该任务,而不必将该方法实现为“异步”。Async/await 很像使用'yield return';它做了一些编译器的魔法来实现'yielding',但枚举本身并不关心你如何实现它。同样,'await' 调用并不关心可等待对象的工作方式,只要它是可等待的即可。

于 2012-08-02T19:10:34.267 回答