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);
}