C# 无等待的尾部异步调用

C# 无等待的尾部异步调用,c#,async-await,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 =

采用此
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();
}

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

您应该可以删除此
wait
async
。事实上,Roslyn(新的C#编译器)团队正在考虑把它变成一个编译器。

是的,这是正确的。当您只是返回一个任务时,您可以省略
async
直接返回
任务,而不必等待
wait

在大多数情况下都可以,但是异常行为有一个重要的区别:返回任务之前的任何异常都将直接抛出,而不是放在任务上。在您的示例中,如果
WebRequest.Create
GetResponse
GetResponseStream
StreamReader(…)
抛出异常,那么在
async
方法中,该异常将被放置在任务上,而在非
async
方法中,该异常将被直接抛出

顺便说一句,如果这是真实代码的代表,我建议使用
HttpClient
,它的设计考虑了
wait

public Task<string> ReadStringFromUrlAsync(string url)
{
  return new HttpClient().GetStringAsync(url);
}
公共任务ReadStringFromUrlAsync(字符串url) { 返回新的HttpClient().GetStringAsync(url); }
如前所述,这是可以的,但您忘记了处理这些资源。现在您需要再次等待。好问题,我早就得出了这个结论,当时我在我们的代码库中看到了冗余等待的分配。@usr感谢这一点,这是一种我正在重构为
async
的方法,这完全没有引起我的注意。这是这个问题的一个坏例子。我不打算编辑,因为答案引用了它。我想让我们假设在我询问的情况下,没有什么应该处理的。谢谢,是的,这是一个来自代码的精确方法,我最初没有编写它,但正在重构为
async
。有点疏忽了我的注意,我的代码中没有处理。肯定会更改为
HttpClient
,但是使用
块时,您不觉得吗?喜欢一旦我有了
使用
块,我就需要再次使用
异步
/
等待
?@weston:如果你使用
使用
块,那么是的。但是大多数真实世界的
HttpClient
使用都会缓存实例。单个
HttpClient
实例能够同时执行任意数量的异步调用。
public Task<string> ReadStringFromUrlAsync(string url)
{
  return new HttpClient().GetStringAsync(url);
}