2012-08-02 128 views
13

我正在编写一个封装第三方Web服务调用的库,并试图使库使用新的异步/等待功能。以下示例中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方法,该方法是否应该添加异步和等待关键字?或者是因为它返回一个任务是好的吗?这种嵌套有更好的模式吗?

我认为DoSomethingAsync方法是正确的方法去这里,是否正确?我相信DoSomethingElseAsync在建立图书馆时似乎是错误的方法。

+0

C#5.0不存在,下一个版本是4.5,你碰巧意味着什么? – 2012-08-02 15:13:34

+9

@Ramhound - 下一个CLR是4.5,下一个语言_is_ C#5 – 2012-08-02 15:19:45

回答

8

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

我不知道为什么DoSomethingAsync只是调用DoSomethingCore,因为DoSomethingAsync可以很容易地被async和使用await

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

编辑:如果你不需要使用await,那么不要使方法asyncasync会增加一些开销(检查通道9为斯蒂芬Toub的异步性能视频的禅宗)。如果你只能返回一个Task(如DoSomethingAsync),那么就这样做。

+0

DoSomethingAsync调用DoSomethingCore,因为在我的真实场景中,我有两个类似的公共方法,它们使用核心方法共享功能。 我将查看ConfigureAwait方法,因为我之前没有见过。 – 2012-08-02 18:57:31

+0

我已经添加了DoSomethingElseAsync()方法来更好地解释我所困惑的内容。我相信你已经充分解释了这一点,并且DoSomethingAsync()方法是一种库方法。 – 2012-08-02 19:02:13

+0

好的。查看更新的答案。 – 2012-08-02 21:03:23

0

下面的制剂是功能性的,但是很可能会造成额外的开销(由于具有用于附加异步二次回调/等待方法。)

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

所以,很简单直接返回任务,因为你可以总是在别处等待该任务,而不必将该方法实施为“异步”。异步/等待很像使用“收益回报”;它会执行一些编译器魔术来实现'yielding',但枚举本身并不关心你如何实现它。同样,只要候选人能够等待,“等待”电话并不在乎等待的工作。