在 .NET 中很难找到工作线程和 I/O 线程的详细但简单的描述
我对这个主题的了解很清楚(但技术上可能不准确):
- 工作线程是这样的线程should使用 CPU 来完成工作;
- I/O 线程(也称为“完成端口线程”)should使用设备驱动程序来完成工作,并且本质上“不执行任何操作”,仅监视非 CPU 操作的完成情况。
不清楚的是:
- 尽管 ThreadPool.GetAvailableThreads 方法返回两种类型的可用线程数,但似乎没有公共 API 来安排 I/O 线程的工作。 .NET 中只能手动创建工作线程?
- 看起来单个 I/O 线程可以监控多个 I/O 操作。这是真的吗?如果是这样,为什么ThreadPool默认有这么多可用的I/O线程?
- 在一些文本中,我读到回调,由 I/O 线程执行 I/O 操作完成后触发。这是真的吗?考虑到这个回调是CPU操作,这不是工作线程的工作吗?
- 更具体地说,ASP.NET 异步页面是否使用 I/O 线程?将 I/O 工作切换到单独的线程而不是增加工作线程的最大数量到底有什么性能优势?是因为单个 I/O 线程确实监视多个操作吗?或者 Windows 在使用 I/O 线程时进行更高效的上下文切换?
.net/CLR 中的术语“工作线程”通常指除主线程之外的任何线程,它代表生成该线程的应用程序执行一些“工作”。 “工作”实际上可能意味着任何事情,包括等待某些 I/O 完成。线程池保留工作线程的缓存,因为创建线程的成本很高。
.net/CLR 中的术语“I/O 线程”是指 ThreadPool 保留的线程,以便从“重叠”win32 调用(也称为“完成端口 I/O”)分派 NativeOverlapped 回调。 CLR 维护自己的 I/O 完成端口,并且可以将任何句柄绑定到它(通过 ThreadPool.BindHandle API)。这里的例子:http://blogs.msdn.com/junfeng/archive/2008/12/01/threadpool-bindhandle.aspx。许多 .net API 在内部使用此机制来接收 NativeOverlapped 回调,尽管典型的 .net 开发人员不会直接使用它。
“工作线程”和“I/O 线程”之间确实没有技术差异——它们都只是普通线程。但 CLR ThreadPool 为每个线程保留单独的池,只是为了避免对工作线程的高需求耗尽所有可用于分派本机 I/O 回调的线程,从而可能导致死锁。 (想象一个应用程序使用所有 250 个工作线程,其中每个线程都在等待某些 I/O 完成)。
开发人员在处理 I/O 回调时确实需要小心,以确保 I/O 线程返回到 ThreadPool——也就是说,I/O 回调代码应该做为回调提供服务所需的最少工作然后将线程的控制权返回给 CLR 线程池。如果需要更多工作,则应将该工作安排在工作线程上。否则,应用程序可能会“劫持”CLR 的保留 I/O 完成线程池以用作普通工作线程,从而导致上述死锁情况。
一些可供进一步阅读的好参考:
win32 I/O 完成端口:http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx托管线程池:http://msdn.microsoft.com/en-us/library/0ka9477y.aspx绑定句柄示例:http://blogs.msdn.com/junfeng/archive/2008/12/01/threadpool-bindhandle.aspx
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)