首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >HttpClient不提供真正的异步操作吗?

HttpClient不提供真正的异步操作吗?
EN

Stack Overflow用户
提问于 2016-10-08 10:21:16
回答 2查看 578关注 0票数 4

我对异步IO操作感到困惑。在这篇文章中,Stephen解释说我们不应该使用Task.Run(() => SomeIoMethod()),因为真正的异步操作应该使用

.NET中的标准P/Invoke异步I/O系统

http://blog.stephencleary.com/2013/11/there-is-no-thread.html

但是,要避免库中的“假异步”。假异步是当组件具有异步就绪API时,但它是通过将同步API封装在线程池线程中实现的。这对ASP.NET上的可伸缩性是适得其反的,一个突出的假异步的例子是Newtonsoft JSON.NET,这是一个非常优秀的库。最好不要调用用于序列化JSON的(假)异步版本;只需调用同步版本即可。假异步的一个更棘手的例子是BCL文件流。打开文件流时,必须为异步访问显式打开它;否则,它将使用假异步,同步阻塞文件读写上的线程池线程。

他建议使用HttpClient,但内部使用Task.Factory.StartNew()

这是否意味着HttpClient提供的不是真正的异步操作?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-10 13:38:43

这是否意味着HttpClient提供的不是真正的异步操作?

说大也大吧。HttpClient处于一个不寻常的位置,因为它的主要实现使用HttpWebRequest,这只是部分异步的。

特别是DNS查找是同步的,我认为可能代理解析也是同步的。在那之后,一切都是异步的。因此,在大多数情况下,DNS是快速的(通常是缓存的),并且没有代理,所以它是异步的。不幸的是,有足够的场景(特别是在公司网络中),同步操作可能导致明显的滞后。

因此,当团队编写HttpClient时,他们有三个选择:

  1. 修正允许完全异步操作的HttpWebRequest (和朋友)。不幸的是,这会破坏相当多的代码。由于继承在这些对象中用作扩展点的方式,添加异步方法将是向后不兼容的。
  2. 编写自己的HttpWebRequest等价物。不幸的是,这将需要大量的工作,而且他们将失去与现有WebRequest-related代码的所有互操作性。
  3. 队列请求到线程池以避免最坏的情况(阻塞UI线程上的同步代码)。不幸的是,这会降低ASP.NET上的可伸缩性,依赖于一个空闲线程池线程,甚至在最好的情况下也会导致最坏的情况发生。

在一个理想的世界(即,当我们有无限的开发人员和测试时间),我更喜欢(2),但我理解他们为什么选择(3)。

另外,您发布的代码显示了一个StartNew,由于它使用了TaskScheduler.Current,它实际上具有引起的问题。这个已经修好了在.NET内核中--不确定修复什么时候会回滚到.NET框架中。

票数 4
EN

Stack Overflow用户

发布于 2016-10-08 14:24:39

不你的假设是错的。

  1. 方法。
  2. 这段代码来自HttpClientHandler,而不是HttpClient,您没有检查该类中的this.startRequest代码。您正在检查的代码是准备方法,它在新线程池中启动任务,并在调用实际代码中启动http请求。
  3. HTTP-connection不是在.NET抽象级别上创建的,我确信在startRequest中您会找到一些P/Invoke方法,它将完成以下实际工作:
代码语言:javascript
运行
复制
- DNS lookup
- Socket connection
- Sending the request
- waiting for the answer
- etc.

  1. 正如您所看到的,所有这些都是真正应该以异步方式调用的逻辑,因为它在.NET框架之外,一些操作可能非常耗时。这正是应该异步调用的逻辑,在等待它期间,.NET线程将在ThreadPool中释放,以处理其他任务。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39931213

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档