【发布时间】:2020-01-23 05:55:28
【问题描述】:
.NET / .NET Core 线程池在内部使用两种不同类别的线程:工作线程和 I/O 完成端口 (IOCP) 线程。两者都只是通常的托管线程,但用于不同的目的。通过不同的 API(例如 Task.Start 或 ThreadPool.QueueUserWorkItem),我可以在工作线程上启动 CPU 密集型异步操作(这不应该阻塞,否则线程池可能会创建额外的工作线程)。
但是执行 I/O 密集型异步操作呢? IOCP 线程在这些情况下的表现如何?具体来说,我有以下问题:
- 如果我启动异步 I/O 操作(例如,针对文件、管道或网络),我怀疑当前线程分派了异步请求。我也知道(通过“通过 C# 进行 CLR”一书)CLR 注册到用于执行重叠异步 I/O 的 I/O 完成端口。我怀疑这个 IOCP 是绑定到异步操作的,以便稍后可以将异步操作结果排队到线程池中。 因此,我的假设是否正确,即启动异步请求时没有触及 IOCP 线程?
- 我怀疑当异步 I/O 操作的结果通过 CLR 的 I/O 完成端口报告时,这就是 IOCP 线程到位的地方。结果排队到线程池,并使用一个 IOCP 线程来处理它。但是,在阅读一些论坛线程like this one on MSDN 时,我感觉IOCP 线程实际上是用于分派请求然后阻塞直到返回结果。 是这样吗?当 I/O 操作由对方系统处理时,IOCP 线程是否阻塞?
-
async await和SynchronizationContext呢? IOCP 线程是否处理异步 I/O 响应,然后例如在 UI 线程上排队继续(假设未调用ConfigureAwait(false))? - Linux/MacOS X 上的 .NET Core 怎么样?没有 I/O 完成端口 - 它们是否以任何方式模拟?
【问题讨论】:
-
There is no thread 总是推荐在这里阅读。
-
这个问题太笼统了。一般来说,不,启动 I/O 请求不需要任何异步代码。 I/O 管理器必须已经处理请求 I/O 的多个进程,因此它自己负责将驱动程序请求排队。 SynchronizationContext 通常没有任何作用,但早期 .NET Framework 版本中的 XxxxAsync() 方法除外,这些方法努力使事件在预期线程上引发。 unix 有自己的风格,macOS 使用 kqueue,Linux 使用 epoll。
-
@Damien_The_Unbeliever 感谢您的链接,Stephen Toub 的帖子几乎回答了我所有的问题。
-
@HansPassant 你是对的,这个问题太宽泛了(或者没有很好地表述)。感谢您对 kqueue 和 epoll 的提示。
-
仅作记录,Stephen Toub 是设计大量 .NET
async系统的天才。斯蒂芬·克利里(“另一个斯蒂芬”)就是喜欢写它的人。
标签: .net asynchronous .net-core threadpool iocp