没有等待的尾调用异步

时间:2015-08-20 08:12:12

标签: c# async-await

采用此async方法:

public async Task<string> ReadStringFromUrlAsync(string url)
{
    WebRequest request = WebRequest.Create(url);
    WebResponse response = request.GetResponse();
    Stream dataStream = response.GetResponseStream();
    var reader = new StreamReader(dataStream);
    return await reader.ReadToEndAsync();
}

因为它会返回另一项任务的结果,我相信我可以取消asyncawait

public Task<string> ReadStringFromUrlAsync(string url)
{
    WebRequest request = WebRequest.Create(url);
    WebResponse response = request.GetResponse();
    Stream dataStream = response.GetResponseStream();
    var reader = new StreamReader(dataStream);
    return reader.ReadToEndAsync();
}

我注意到在发生异常时调用堆栈不会提及ReadStringFromUrlAsync,以这种方式删除尾部调用上的aysnc / await是否有任何其他缺点。

3 个答案:

答案 0 :(得分:4)

在大多数情况下都很好,但是在异常行为方面存在重要差异:在返回任务之前的任何异常将直接抛出而不是放在任务上。在您的示例中,如果WebRequest.CreateGetResponseGetResponseStreamStreamReader(..)抛出,则在async方法中将异常放在任务上,同时在非async方法中,将直接抛出异常。

顺便说一句,如果那是您真实代码的代表,我建议改为使用HttpClient代替await设计{/ 1}}:

public Task<string> ReadStringFromUrlAsync(string url)
{
  return new HttpClient().GetStringAsync(url);
}

答案 1 :(得分:2)

删除此awaitasync时,您应该没问题。实际上,Roslyn(新的C#编译器)团队正在考虑将其作为编译器optimization

答案 2 :(得分:1)

是的,这是正确的。当您刚刚返回任务时,您可以省略async并直接返回Task,而不会await