在看微软的ASP.NET - 将 ASP.NET 用作高性能文件下载器 示例里面用到了IO 线程,以前打算自己撸的,这里贴出来 已标记一下:
// A delegate's BeginInvoke runs on a "worker thread" inside the CLR ThreadPool.
// This allows you to run a delegate on a "completion port thread" inside the CLR ThreadPool
// instead of a "worker thread" by calling IOBeginInvoke instead of BeginInvoke.
// In a nut shell, this mechanism basically skips the actual system I/O and simply posts a
// completion delegate to the completion port queue so the completion delegate will be
// executed by a "completion port thread" that is working the completion port queue.
//
// Example:
// delegate.BeginInvoke => executes delegate on "worker thread".
// delegate.IOBeginInvoke => executes delegate on "completion port thread".
//
//
// Extremely simplified explanation:
//
// CLR ThreadPool is made up of two pools of threads: "worker threads" and "completion port threads".
//
// Basically you can either queue a user work item which runs the delegate on a "worker thread",
// or queue a native overlapped item which runs the completion delegate on a "completion port thread".
// ThreadPool.QueueUserWorkItem (and delegate.BeginInvoke) => executes delegate on "worker thread".
// ThreadPool.UnsafeQueueNativeOverlapped => executes completion delegate on "completion port thread".
//
// (CLR ThreadPool)
// / \
// [worker threads] [completion port threads]
//
// o o oo o oo _____________post to queue using ThreadPool.UnsafeQueueNativeOverlapped
// o o oo o o | (i.e. PostQueuedCompletionStatus)
// o o o o o v
// oo o oo o o | |
// o oo oo o | | <----------completion port queue (one per process)
// |__|
// ^ oo o
// | o o oo <---------completion port threads (work the completion port queue)
// | (cpu)(cpu)(cpu)(cpu) (i.e. GetQueuedCompletionStatus in loop)
// |
// | ^
// | |
// | |
// | |
// | |
// | Each individual completion delegate is given to the completion port queue to execute,
// | and the "completion port threads" working the completion port queue execute the delegate.
// | (This has much less risk of thread explosion because each delegate just gets posted to the
// | completion port queue, instead of being given to its own individual thread. Basically
// | the queue grows, n