每CLR一个线程池:这个线程池由CLR控制的所有APPDomain共享。如果一个进程中加载了多个CLR,那么每个CLR都有它自己的线程池。CLR初始化时,线程池中是没有线程的,在内部,线程池维护一个操作请求队列。应用程序想执行一个异步操作时,就调用某个方法,将一个记录项(entry)追加到线程池的队列中。线程池的代码从这个队列中提取记录项,将这个记录项派遣(dispatch)给一个线程池线程。如果线程池中没有线程,就创建一个新线程。当完成任务后,线程不会被销毁,相反,会返回线程池并进入空闲状态,等待另一个请求。由于线程不销毁所以不产生额外的性能损失。在内部,线程池将线程分为工作者(worker)线程和I/O线程。应用程序要求线程池执行一个异步的计算限制的操作时(这个操作可能发起一个I/O限制的操作),使用的就是工作者线程。I/O线程用于通知你的代码一个异步I/O限制操作依据完成。
执行简单的计算限制操作
要将一个异步的、计算限制的操作放到线程池的队列中,通常可以调用ThreadPool类定义的方法 QueueUserWorkItem
执行上下文
每个线程都关联一个执行上下文数据结构。包括安全设置(压缩栈、Thread的Principal属性和Windows身份)、宿主设置以及逻辑调用上下文数据。默认情况下,线程执使用另外一个线程执行任务时,前者的执行上下文应该流行辅助线程。
System.Threading命名空间有一个ExecutionContext类,它允许你控制上下文流动。
public static void Main() {
// Put some data into the Main thread's logical call context
CallContext.LogicalSetData("Name", "Jeffrey");
// Initiate some work to be done by a thread pool thread
// The thread pool thread can access the logical call context data
ThreadPool.QueueUserWorkItem( state => Console.WriteLine("Name={0}", CallContext.LogicalGetData("Name")));
// Now, suppress the flowing of the Main thread's execution context ExecutionContext.SuppressFlow();
// Initiate some work to be done by a thread pool thread
// The thread pool thread CANNOT access the logical call context data
ThreadPool.QueueUserWorkItem( state => Console.WriteLine("Name={0}", CallContext.LogicalGetData("Name")));
// Restore the flowing of the Main thread's execution context in case
// it employs more thread pool threads in the future ExecutionContext.RestoreFlow();
Console.ReadLine();
}
运行结果是
Name=Jeffrey
Name=