public ref class ThreadPool abstract sealed
public ref class ThreadPool sealed
public static class ThreadPool
public sealed class ThreadPool
type ThreadPool = class
Public Class ThreadPool
Public NotInheritable Class ThreadPool
ThreadPool

在以下示例中,主应用程序线程将名为 ThreadProc 的方法排队,以便在线程池线程上执行,休眠一秒钟,然后退出。 方法 ThreadProc 仅显示一条消息。

using namespace System;
using namespace System::Threading;
ref class Example
public:
   // This thread procedure performs the task.
   static void ThreadProc(Object^ stateInfo)
      // No state object was passed to QueueUserWorkItem, so stateInfo is 0.
      Console::WriteLine( "Hello from the thread pool." );
int main()
   // Queue the task.
   ThreadPool::QueueUserWorkItem(gcnew WaitCallback(Example::ThreadProc));
   Console::WriteLine("Main thread does some work, then sleeps.");
   Thread::Sleep(1000);
   Console::WriteLine("Main thread exits.");
   return 0;
// The example displays output like the following:
//       Main thread does some work, then sleeps.
//       Hello from the thread pool.
//       Main thread exits.
using System;
using System.Threading;
public class Example 
    public static void Main() 
        // Queue the task.
        ThreadPool.QueueUserWorkItem(ThreadProc);
        Console.WriteLine("Main thread does some work, then sleeps.");
        Thread.Sleep(1000);
        Console.WriteLine("Main thread exits.");
    // This thread procedure performs the task.
    static void ThreadProc(Object stateInfo) 
        // No state object was passed to QueueUserWorkItem, so stateInfo is null.
        Console.WriteLine("Hello from the thread pool.");
// The example displays output like the following:
//       Main thread does some work, then sleeps.
//       Hello from the thread pool.
//       Main thread exits.
Imports System.Threading
Public Module Example
    Public Sub Main()
        ' Queue the work for execution.
        ThreadPool.QueueUserWorkItem(AddressOf ThreadProc)
        Console.WriteLine("Main thread does some work, then sleeps.")
        Thread.Sleep(1000)
        Console.WriteLine("Main thread exits.")
    End Sub
    ' This thread procedure performs the task.
    Sub ThreadProc(stateInfo As Object)
        ' No state object was passed to QueueUserWorkItem, so stateInfo is null.
        Console.WriteLine("Hello from the thread pool.")
    End Sub
End Module
' The example displays output like the following:
'       Main thread does some work, then sleeps.
'       Hello from the thread pool.
'       Main thread exits.

如果注释掉对 方法的调用 Thread.Sleep ,则主线程将在方法在线程池线程上运行之前退出。 线程池使用后台线程,如果所有前台线程都终止,后台线程不会使应用程序保持运行。 (这是一个争用条件的简单示例。)

许多应用程序创建的线程花费大量时间处于休眠状态,等待事件发生。 其他线程可能进入睡眠状态,只是定期唤醒以轮询更改或更新状态信息。 通过线程池,可以通过为应用程序提供由系统管理的工作线程池来更高效地使用线程。 使用线程池线程的操作示例包括:

  • 创建 TaskTask<TResult> 对象以异步执行某些任务时,默认情况下,任务计划在线程池线程上运行。

  • 异步计时器使用线程池。 线程池线程从 System.Threading.Timer 类执行回调,并从 类引发事件 System.Timers.Timer

  • 使用已注册的等待句柄时,系统线程监视等待句柄的状态。 等待操作完成后,线程池中的工作线程将执行相应的回调函数。

  • 调用 QueueUserWorkItem 方法将方法排队以便在线程池线程上执行时。 为此,请将 方法 WaitCallback 传递给委托。 委托具有签名

    void WaitCallback(Object state)
    
    Sub WaitCallback(state As Object)
    

    其中 state 是一个对象,其中包含委托要使用的数据。 可以通过调用 QueueUserWorkItem(WaitCallback, Object) 方法将实际数据传递给委托。

    托管线程池中的线程是后台线程。 也就是说,其 IsBackground 属性为 true。 这意味着 ThreadPool ,在退出所有前台线程后,线程不会使应用程序保持运行。

    当线程池重复使用某个线程时,它不会清除线程本地存储或用 ThreadStaticAttribute 属性标记的字段中的数据。 因此,当方法检查线程本地存储或用 ThreadStaticAttribute 属性标记的字段时,它找到的值可能会从之前使用线程池线程时留下。

    还可以将与等待操作无关的工作项排队到线程池。 若要请求由线程池中的线程处理工作项,请调用 QueueUserWorkItem 方法。 此方法采用对方法或委托的引用作为参数,该方法或委托将由从线程池中选择的线程调用。 在工作项排队后,无法取消它。

    计时器队列计时器和已注册的等待操作也使用线程池。 它们的回调函数将排队到线程池。

    每个进程有一个线程池。 从 .NET Framework 4 开始,进程的线程池的默认大小取决于若干因素,例如虚拟地址空间的大小。 进程可以调用 GetMaxThreads 方法,以确定线程数。 可以使用 方法更改 SetMaxThreads 线程池中的线程数。 每个线程使用默认堆栈大小,并按默认优先级运行。

    托管.NET Framework的非托管代码可以使用 mscoree.h 文件中定义的 函数更改线程池CorSetMaxThreads的大小。

    线程池按需提供新的工作线程或 I/O 完成线程,直到达到每个类别的最大值。 达到最大值时,线程池可以在该类别中创建其他线程,或等到某些任务完成。 从 .NET Framework 4 开始,线程池创建和销毁工作线程以优化吞吐量,吞吐量被定义为每个单位时间完成的任务数。 线程过少可能无法实现可用资源的最优利用,而线程过多则可能增加资源争用。

    需求较低时,线程池线程的实际数量可以低于最小值。

    可以使用 GetMinThreads 方法来获取这些最小值。

    可以使用 SetMinThreads 方法增加最小线程数。 但是,不必要地增加这些值可能导致性能问题。 如果在同一时间开始太多的任务,则所有任务均可能会很慢。 大多数情况下,使用自己的分配线程算法,线程池将更好地执行任务。

  •