gpt4 book ai didi

c# - 为什么要等待异步请求和读取其内容?

转载 作者:太空狗 更新时间:2023-10-29 21:27:38 28 4
gpt4 key购买 nike

为什么在 .NET Web API 中有必要有一个方法来异步读取 HTTP 响应的内容,因为已经有一个方法可以异步发出请求?换句话说,如果我使用 HttpClient.GetAsync(或 PostAsyncPutAsync 等),代码是否真的更加异步了还异步读取内容?如果是这样,如何/为什么?

这是:

using (var client = new HttpClient()) {
var response = await client.GetAsync("...");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsAsync<Foo>();
}

比这更好:

using (var client = new HttpClient()) {
var response = await client.GetAsync("...");
response.EnsureSuccessStatusCode();
return response.Content.ReadAsAsync<Foo>().Result;
}

为什么?

最佳答案

Why is it necessary in .NET Web API to have a a method that reads the content of an HTTP response asynchronously, given that there is already a method to make the request asynchronously?

因为它可以。这两种方法做不同的事情。第一个通过线路发送网络请求,第二个从收到的 Stream 中读取.

由于发出网络请求和从流中读取都是 IO 绑定(bind)操作,因此您可以利用它们公开的异步 API。

if I am using HttpClient.GetAsync (or PostAsync, or PutAsync, etc), is the code really any more asynchronous by also reading the content out asynchronously? If so, how/why?

说“更异步”听起来有点奇怪。但是,是的,前一个例子比后者更异步。

让我们尝试描绘以下场景:您创建了一个负责与第三方服务对话的库。你暴露一个方法,让我们称之为FooAsync ,它返回一个非常大的 List<Foo> .用户知道 API 是异步的,因此他很乐意从 UI 线程调用它,而不用担心它会长时间阻塞。

现在,让我们看看当他使用每种方法进行调用时发生了什么:

  1. 我们执行 FooAsync并发出 http 请求,在到达第一个 await 时将控制权交给调用者.然后,继续执行命中第二个 await它从接收到的流中读取,再次将控制权交还给调用者,直到完成。一直以来,UI 都可以自由处理消息,因为这两个主要操作都是异步完成的。

  2. 我们执行 FooAsync然后我们发出 http 请求。我们放弃对第一个 await 的控制, 一切都很好。然后,我们收到响应并同步读取底层流。当我们读取(并且让我们记住我们正在读取一个非常大的流)时,UI 线程在 IO 操作上被阻塞,无法处理任何其他消息。

我们的第二种情况绝对是不希望的,更糟糕​​的是,出乎意料。我们告诉用户他收到了 async api,但我们最终会阻塞很长时间。不仅如此,如果Task.Result从 UI 线程调用,它可能会死锁。

使用 await 的好处在这两个操作上,您创建了一个真正的异步 api,不会在阻塞 IO 操作上浪费任何时间,并且不会让任何通过阻塞调用您的方法的人感到惊讶。

我建议阅读 Best Practices in Asynchronous Programming其中讨论了所有这些边缘情况。

总而言之,如果您可以“一路走下去”,那就去做吧。

关于c# - 为什么要等待异步请求和读取其内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24459450/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com