1 线程池的概念
许多应用程序使用多个线程,但这些线程经常在休眠状态中耗费大量的时间来等待事件发生。其他线程可能进入休眠状态,并且仅定期被唤醒以轮询更改或更新状态信息,然后再次进入休眠状态。为了简化对这些线程的管理,.NET框架为每一个进程提供了一个线程池,使应用程序能够根据需要来有效地利用多个线程。一个线程监视排到线程池的若干个等待操作的状态。当一个等待操作完成时,线程池中的一个辅助线程就会执行对应的回调函数。线程池中的线程由系统进行管理,程序员不需要费力于线程管理,可以集中精力处理应用程序任务。
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间之后创建另一个辅助线程。但线程的数目永远不会超过最大值。超过最大值的其他线程可以排队,但它们要等到其他线程完成后才启动。
2 线程池的应用范围线程池特别适合于执行一些需要多个线程的任务。使用线程池能够优化这些任务的执行过程,从而提高吞吐量,它不仅能够使系统针对此进程优化该执行过程,而且还能够使系统针对计算机上的其他进程优化该执行过程。如果需要启动多个不同的任务,而不想分别设置每个线程的属性,则可以使用线程池。
如果应用程序需要对线程进行特定的控制,则不适合使用线程池,需要创建并管理自己的线程。
在以下几种情况下,适合于使用线程池线程:
(1)不需要前台执行的线程。
(2)不需要在使用线程具有特定的优先级。
(3)线程的执行时间不易过长,否则会使线程阻塞。由于线程池具有最大线程数限制,因此大量阻塞的线程池线程可能会阻止任务启动。
(4)不需要将线程放入单线程单元。所有 ThreadPool 线程均不处于多线程单元中。
(5)不需要具有与线程关联的稳定标识,或使某一线程专用于某一任务。
3 ThreadPool类在多线程的程序中,经常会出现两种情况:一种是在应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应,这一般使用ThreadPool(线程池)来解决;另一种情况是在线程平时都处于休眠状态,只是周期性地被唤醒,这一般使用Timer(定时器)来解决。下面对ThreadPool类进行详细说明。
ThreadPool类提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。该类提供一个由系统维护的线程池(可以看作一个线程的容器),该容器需要Windows 2000以上系统支持,因为其中某些方法调用了只有高版本的Windows才有的API函数。
下面介绍一下该类所提供的方法,如表1所示。
表1 ThreadPool类的方法
方法 描述 BindHandle 将操作系统句柄绑定到ThreadPool GetAvailableThreads 检索由GetMaxThreads方法返回的最大线程池线程数和当前活动线程数之间的差值 GetMaxThreads 检索可以同时处于活动状态的线程池请求的数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用 GetMinThreads 检索线程池在新请求预测中维护的空闲线程数 QueueUserWorkItem 将方法排入队列以便执行。此方法在有线程池线程变得可用时执行 RegisterWaitForSingleObject 注册正在等待WaitHandle的委托 SetMaxThreads 设置可以同时处于活动状态的线程池的请求数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用 SetMinThreads 设置线程池在新请求预测中维护的空闲线程数 UnsafeQueueNativeOverlapped 将重叠的 I/O 操作排队以便执行 UnsafeQueueUserWorkItem 注册一个等待 WaitHandle 的委托 UnsafeRegisterWaitForSingleObject 将指定的委托排队到线程池