在.NET中很难找到对工作线程和I/O线程的详细而简单的描述

关于这个话题,我很清楚(但在技术上可能不准确):

  • 工作线程是should使用CPU进行工作的线程;
  • I/O线程(也称为"完成端口线程")should为它们的工作使用设备驱动程序,并且本质上"什么也不做",只监视非CPU操作的完成.

目前尚不清楚的是:

  • 虽然方法是线程池.GetAvailableThreads返回两种类型的可用线程数,似乎没有公共API来安排I/O线程的工作.只能在中手动创建工作线程.网
  • 似乎单个I/O线程可以监控多个I/O操作.是真的吗?如果是,为什么线程池默认情况下有这么多可用I/O线程?
  • 在一些文本中,我读到了I/O线程执行I/O操作完成后触发的回调.是真的吗?考虑到此回调是CPU操作,这不是工作线程的作业(job)吗?
  • 更具体地说,做ASP.NET异步页面用户I/O线程?将I/O工作切换到单独的线程,而不是增加工作线程的最大数量,究竟有什么性能优势?是因为单个I/O线程监视多个操作吗?或者Windows在使用I/O线程时会进行更高效的上下文切换?

推荐答案

Net/CLR中的术语"工作线程"通常只是指除代表生成线程的应用程序执行某些"工作"的主线程之外的任何线程."工作"实际上意味着任何事情,包括等待一些I/O完成.ThreadPool保留工作线程的缓存,因为创建线程的成本很高.

中的术语"I/O线程".net/CLR是指线程池保留的线程,用于从"重叠的"win32调用(也称为"完成端口I/O")调度本机重叠回调.CLR维护自己的I/O完成端口,并可以将任何句柄绑定到该端口(通过ThreadPool.BindHandle API).这里的例子是:http://blogs.msdn.com/junfeng/archive/2008/12/01/threadpool-bindhandle.aspx.许多的net API在内部使用这种机制来接收本机重叠回调,尽管这种机制是典型的.net开发者永远不会直接使用它.

"工作线程"和"I/O线程"在技术上实际上没有区别--它们都只是普通线程.但是,CLRThreadPool for each 线程保留了单独的池,以避免工作线程的高需求耗尽了所有可用于分派本机I/O回调的线程,从而可能导致死锁.(设想一个应用程序使用全部250个工作线程,其中每个线程都在等待一些I/O完成).

在处理I/O回调时,开发人员确实需要格外小心,以确保I/O线程返回到线程池——也就是说,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

.net相关问答推荐

";Make Async ValueTask/ValueTask方法分期分配发生了什么?

使用字典作为数据源绑定组合框

.Include() 与 .Load() 在 EntityFramework 中的性能

如何让 DateTimePicker 显示一个空字符串?

RNGCryptoServiceProvider 的优缺点

如何从字符串中删除所有字母字符?

如何将 NuGet 与 Visual C# Express 一起使用?

你如何调试 MVC 4 API 路由?

在 ToString() 之前判断 null

我不了解应用程序域

List 和 IEnumerable 的实际区别

加载程序集、查找类和调用 Run() 方法的正确方法

如何确定字符串是 C# 中的有效 IPv4 还是 IPv6 地址?

使用语句与最终try

我应该如何删除 DbSet 中的所有元素?

如何获取命名空间中的所有类?

Guid.Parse() 或 new Guid() - 有什么区别?

读取 XML(从字符串)并获取一些字段 - 读取 XML 时出现问题

如果选中,则更改列表框项的 WPF DataTemplate

判断数据表中是否包含空值的最佳方法