我对异步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提供的不是真正的异步操作?
发布于 2016-10-10 13:38:43
这是否意味着HttpClient提供的不是真正的异步操作?
说大也大吧。HttpClient处于一个不寻常的位置,因为它的主要实现使用HttpWebRequest,这只是部分异步的。
特别是DNS查找是同步的,我认为可能代理解析也是同步的。在那之后,一切都是异步的。因此,在大多数情况下,DNS是快速的(通常是缓存的),并且没有代理,所以它是异步的。不幸的是,有足够的场景(特别是在公司网络中),同步操作可能导致明显的滞后。
因此,当团队编写HttpClient时,他们有三个选择:
HttpWebRequest (和朋友)。不幸的是,这会破坏相当多的代码。由于继承在这些对象中用作扩展点的方式,添加异步方法将是向后不兼容的。HttpWebRequest等价物。不幸的是,这将需要大量的工作,而且他们将失去与现有WebRequest-related代码的所有互操作性。在一个理想的世界(即,当我们有无限的开发人员和测试时间),我更喜欢(2),但我理解他们为什么选择(3)。
另外,您发布的代码显示了一个StartNew,由于它使用了TaskScheduler.Current,它实际上具有引起的问题。这个已经修好了在.NET内核中--不确定修复什么时候会回滚到.NET框架中。
发布于 2016-10-08 14:24:39
不你的假设是错的。
HttpClientHandler,而不是HttpClient,您没有检查该类中的this.startRequest代码。您正在检查的代码是准备方法,它在新线程池中启动任务,并在调用实际代码中启动http请求。startRequest中您会找到一些P/Invoke方法,它将完成以下实际工作:- DNS lookup
- Socket connection
- Sending the request
- waiting for the answer
- etc.
ThreadPool中释放,以处理其他任务。https://stackoverflow.com/questions/39931213
复制相似问题