Delphi ThreadPool 线程池(Delphi2009以上版本适用)

http://blog.sina.com.cn/s/blog_6250a9df0101kref.html

在网上查找Delphi线程池,结果发现寥寥无几。

看了半天源代码,弄得一头雾水,觉得不容易理解和使用,于是自己想写一个线程池。

什么样的线程池更好呢?

我觉得使用起来要可靠,并且一定要简单,这样才是更好的。

我写的线程池就是这样一个标准,使用非常简单,只传入自己要执行的方法就可以了,

其实大家最后就是关注自己要操作的方法,其余的交给线程池。全部源代码如下:

{
  {单元:ThreadPoolUint}
  {说明:线程池}
  //
  {Rev. 开发日期      开发者   EMail}
  {Ver.1.0.0   2011/05/05    孙玉良   [email protected]}
}

unit ThreadPoolUint;

{ 定义多线程共享读独占写条件编译}
{$DEFINE MULTI_THREAD_WRITE_READ}

interface

uses System.Classes, System.SysUtils, System.Math, System.Generics.Collections,
  Vcl.Forms;

type

  { 要执行任务的记录}
  TaskRec = record
    isSynchronize : Boolean; { 是否需要同步执行}
    TaskProc : TThreadProcedure; { 要执行任务的方法}
  end;

  { 执行具体任务线程}
  TExecuteThread = class( TThread )
  private
    FProc : TThreadProcedure; { 要执行的任务方法}
    FIsCanTask : Boolean; { 是否可以执行任务}
    FIsSynchronize : Boolean; { 是否用同步执行}

    procedure showThreadID; { 显示线程编号(测试使用)}
  protected
    procedure Execute; override;
  public
    constructor Create( CreateSuspended : Boolean ); overload;
  public
    procedure StartTask( task : TaskRec ); { 执行任务}
  end;

  { 线程池类(单例模式的类,做为全局使用的类)}
  ThreadPool = class( TObject )
  private
{$IFDEF MULTI_THREAD_WRITE_READ}
    FMREWSync : TMREWSync; { 共享读独占写变量}
{$ENDIF}
    FTaskQueue : TQueue< TaskRec >; { 要执行任务队列}
    FTaskThreadList : TList< TExecuteThread >; { 执行任务线程List}
    FThreadMin : Integer; { 最小线程数量}
    FThreadMax : Integer; { 最大线程数量}

    { 共享读独占写方法}
    procedure BeginWrite; { 独占写开始}
    procedure EndWrite; { 独占写结束}
    procedure BeginRead; { 共享读开始}
    procedure EndRead; { 共享读结束}

    procedure StopTaskAndFree; { 停止执行任务并释放相关资源}

  protected
    constructor CreateInstance( const minCount : Integer = 5;
      const maxCount : Integer = 20 );
    class function AccessInstance( Request : Integer;
      const minCount : Integer = 5; const maxCount : Integer = 20 )
      : ThreadPool;
  public
    constructor Create; { 构造函数}
    destructor destroy; override; { 析构函数}
    class function Instance( const minCount : Integer = 5;
      const maxCount : Integer = 20 ) : ThreadPool; { 实例化函数,客户端调用此函数}
    class procedure ReleaseInstance; { 释放资源函数,客户端调用此函数}

    procedure AddTask( task : TaskRec ); { 添加要执行的任务}
    function IsHaveTask : Boolean; { 是否有要执行的任务}
    procedure ExecuteTask; { 执行任务}
    function DoNextTask( executeThread : TExecuteThread ) : Boolean; { 执行下一任务}
    function IsSuspend( executeThread : TExecuteThread ) : Boolean; { 挂起线程}

    function GetPoolState : string; { 得到线程池状态}

  end;

implementation

{$J+}

{ MainUnit是为了测试引入的窗体单元,实际使用时候删除此单元和相关代码 }
uses MainUnit;

{ -----------------------------------------------------------------------------}

{ 构造函数}
constructor ThreadPool.Create;
begin
  inherited Create;
  raise Exception.CreateFmt( ‘Utils类只能通过Instance方法来创建和访问%s的实例!‘,
    [ ClassName ] );
end;

{ 创建实例方法}
constructor ThreadPool.CreateInstance( const minCount : Integer = 5;
  const maxCount : Integer = 20 );
var
  i : Integer;
begin
  inherited Create;

  { 需要在构造函数中初始化数据全部在此初始化}

{$IFDEF MULTI_THREAD_WRITE_READ}
  { 创建多线程共享读独占写变量}
  Self.FMREWSync := TMREWSync.Create;
{$ENDIF}
  Self.FTaskQueue := TQueue< TaskRec >.Create; { 实例化要执行的任务队列}
  Self.FTaskThreadList := TList< TExecuteThread >.Create; { 实例化执行任务线程List}

  Self.FThreadMin := minCount; { 最小线程数量}
  Self.FThreadMax := maxCount; { 最大线程数量}

  { 创建最小数量的线程}
  for i := 0 to minCount - 1 do
  begin
    { 把线程添加到线程List中}
    Self.FTaskThreadList.Add( TExecuteThread.Create( true ) );
  end;

end;

{ 析构函数}
destructor ThreadPool.destroy;
begin

  { 需要析构前完成操作全部在此完成}

  Self.StopTaskAndFree; { 释放线程池资源}

{$IFDEF MULTI_THREAD_WRITE_READ}
  { 释放多线程共享读独占写变量}
  Self.FMREWSync.Free;
{$ENDIF}
  if AccessInstance( 0 ) = Self then
  begin
    AccessInstance( 2 );
  end;

  inherited destroy;
end;

class function ThreadPool.AccessInstance( Request : Integer;
  const minCount : Integer = 5; const maxCount : Integer = 20 ) : ThreadPool;
const
  FInstance : ThreadPool = nil;
begin
  {
    AccessInstance(0):不作任何处理,供释放实例对象时使用。
    AccessInstance(1):存在该实例时直接使用,不存在时则创建该实例。
    AccessInstance(2):返回一个空指针,用于重新设置实例。
  }
  case Request of
    0 :
      ;
    1 :
      if not Assigned( FInstance ) then
      begin
        FInstance := CreateInstance( minCount, maxCount );
      end;
    2 :
      FInstance := nil;
  else
    raise Exception.CreateFmt( ‘ %d 是AccessInstance()中的非法调用参数。‘, [ Request ] );
  end;
  Result := FInstance;
end;

{ 得到类实例}
class function ThreadPool.Instance( const minCount : Integer = 5;
  const maxCount : Integer = 20 ) : ThreadPool;
begin
  { 返回实例}
  Result := AccessInstance( 1, minCount, maxCount );
end;

{ 释放资源}
class procedure ThreadPool.ReleaseInstance;
begin
  AccessInstance( 0 ).Free;
end;

{ ---- 类函数结束 ---- }

procedure ThreadPool.StopTaskAndFree;
var
  whileCount : Integer; { while循环计数变量}
  taskThread : TExecuteThread;
begin
  { 1,释放线程List}
  try
    Self.BeginWrite;

    whileCount := 0; { while循环计数默认值为0}
    while whileCount < Self.FTaskThreadList.count do
    begin
      taskThread := Self.FTaskThreadList.Items[ whileCount ]; { 得到工作线程}
      Self.FTaskThreadList.Delete( whileCount ); { 从线程列表中删除线程}
      taskThread.Terminate; { 终止线程}

      Inc( whileCount ); { while循环计数递增}
    end;

  finally
    Self.EndWrite;
    Self.FTaskThreadList.Free; { 释放线程List}
  end;

  { 2,释放任务队列}
  Self.FTaskQueue.Clear;
  Self.FTaskQueue.Free;

end;

{ 独占写开始}
procedure ThreadPool.BeginWrite;
begin
{$IFDEF MULTI_THREAD_WRITE_READ}
  Self.FMREWSync.BeginWrite;
{$ENDIF}
end;

{ 独占写结束}
procedure ThreadPool.EndWrite;
begin
{$IFDEF MULTI_THREAD_WRITE_READ}
  Self.FMREWSync.EndWrite;
{$ENDIF}
end;

{ 共享读开始}
procedure ThreadPool.BeginRead;
begin
{$IFDEF MULTI_THREAD_WRITE_READ}
  Self.FMREWSync.BeginRead;
{$ENDIF}
end;

{ 共享读结束}
procedure ThreadPool.EndRead;
begin
{$IFDEF MULTI_THREAD_WRITE_READ}
  Self.FMREWSync.EndRead;
{$ENDIF}
end;

{ 给线程池添加任务}
procedure ThreadPool.AddTask( task : TaskRec );
begin

  { 添加任务到线程池中}
  try
    Self.BeginWrite;
    Self.FTaskQueue.Enqueue( task ); { 把要执行任务加入任务队列}
  finally
    Self.EndWrite;
  end;

end;

{ 是否有要执行的任务}
function ThreadPool.IsHaveTask : Boolean;
var
  temp : Boolean;
begin

  temp := false;

  try
    Self.BeginRead;

    { 判断有要执行的任务}
    if Self.FTaskQueue.count > 0 then
    begin
      temp := true;
    end;
  finally
    Self.EndRead;
  end;

  Result := temp;
end;

{ 执行任务}
procedure ThreadPool.ExecuteTask;
var
  whileCount : Integer; { while循环计数变量}
  isCanCreateThread : Boolean; { 是否可以创建新线程}
  curThread : TExecuteThread;
begin

  { 在主界面memo中显示信息}
  Form1.log( ‘开始执行任务‘ ); { 测试使用,正式使用删除}

  if Self.IsHaveTask then
  begin
    { 1,判断是否有可以执行任务线程,如果有直接让线程执行}
    try
      Self.BeginRead;

      whileCount := 0; { while循环计数变量默认值为0}
      while whileCount < Self.FTaskThreadList.count do
      begin

        { 判断当前线程为挂起状态}
        if Self.FTaskThreadList.Items[ whileCount ].Suspended then
        begin
          Self.FTaskThreadList.Items[ whileCount ].Resume; { 唤醒挂起线程}
        end;

        Inc( whileCount ); { while循环计数递增}

      end;

    finally
      Self.EndRead;

      { 判断有要执行的任务}
      if Self.IsHaveTask then
      begin

        { 是否可以创建新线程默认值为false}
        isCanCreateThread := false;

        try
          Self.BeginRead;

          { 判断当前线程总数小于最大线程数量}
          if Self.FTaskThreadList.count < Self.FThreadMax then
          begin
            isCanCreateThread := true;
            {/ /是否可以创建新线程为true}
          end;

        finally
          Self.EndRead;

          { 判断可以创建新线程}
          if isCanCreateThread then
          begin

            while Self.FTaskThreadList.count < Self.FThreadMax do
            begin
              { 创建新线程}
              curThread := TExecuteThread.Create( true );

              try
                Self.BeginWrite;
                { 把新线程加入线程List}
                Self.FTaskThreadList.Add( curThread );
              finally
                Self.EndWrite;
              end;

              curThread.Resume;
            end;

          end;

        end;

      end;

    end;
  end;

end;

{ 执行下一任务}
function ThreadPool.DoNextTask( executeThread : TExecuteThread ) : Boolean;
var
  isDoNextTask : Boolean; { 是否执行下一任务}
  nextTaskRec : TaskRec; { 下一任务结构}
  temp : Boolean;
begin

  temp := false; { 返回布尔值默认值为false}

  try

    isDoNextTask := false; { 是否执行下一任务默认值为false}

    Self.BeginWrite;

    { 判断有要执行的任务}
    if Self.FTaskQueue.count > 0 then
    begin
      nextTaskRec := Self.FTaskQueue.Dequeue;
      isDoNextTask := true; { 是否执行任务为true}
      temp := true; { 返回布尔值为true}
    end;

  finally
    Self.EndWrite;

    { 判断执行下一任务}
    if isDoNextTask then
    begin
      executeThread.StartTask( nextTaskRec ); { 执行任务}
    end;

  end;

  Result := temp;
end;

{ 判断线程是否需要挂起}
function ThreadPool.IsSuspend( executeThread : TExecuteThread ) : Boolean;
var
  temp : Boolean;
  isRemove : Boolean;
begin

  temp := false;

  try
    Self.BeginRead;

    isRemove := false; { 是否从线程List中删除当前线程默认值为false}

    { 判断线程数量是否大于最小线程数量}
    if Self.FTaskThreadList.count > Self.FThreadMin then
    begin
      isRemove := true; { 是否从线程List中删除当前线程为true}
    end else begin
      temp := true; { 是否挂起为true}
    end;
  finally
    Self.EndRead;

    { 判断从线程List中删除当前线程}
    if isRemove then
    begin
      try
        Self.BeginWrite;

        { 从线程List中删除当前线程}
        Self.FTaskThreadList.Remove( executeThread );
      finally
        Self.EndWrite;
      end;
    end;

  end;

  Result := temp;

end;

{ 得到线程池状态}
function ThreadPool.GetPoolState : string;
var
  temp : string; { 返回值变量}
  i : Integer; { 循环计数变量}
  curThread : TExecuteThread;
begin

  temp := ‘线程状态:‘ + #13#10;;

  temp := temp + ‘最小线程数:‘ + inttostr( Self.FThreadMin ) + #13#10;
  temp := temp + ‘最大线程数:‘ + inttostr( Self.FThreadMax ) + #13#10;

  try
    Self.BeginRead;

    temp := temp + ‘线程总数:‘ + inttostr( Self.FTaskThreadList.count ) + #13#10;
    temp := temp + #13#10;
    temp := temp + ‘线程详细信息:‘ + #13#10;
    temp := temp + #13#10;

    for i := 0 to Self.FTaskThreadList.count - 1 do
    begin
      curThread := Self.FTaskThreadList.Items[ i ];
      temp := temp + ‘线程-‘ + inttostr( i + 1 ) + #13#10;
      temp := temp + ‘线程编号:‘ + inttostr( curThread.ThreadID ) + #13#10;

      { 是否挂起}
      if curThread.Suspended then
      begin
        temp := temp + ‘是否挂起: True‘ + #13#10;
      end else begin
        temp := temp + ‘是否挂起: False‘ + #13#10;
      end;

      { 是否可以执行任务}
      if curThread.FIsCanTask then
      begin
        temp := temp + ‘是否可以执行: True‘ + #13#10;
      end else begin
        temp := temp + ‘是否可以执行: False‘ + #13#10;
      end;

      { 是否同步执行任务}
      if curThread.FIsSynchronize then
      begin
        temp := temp + ‘是否同步执行: True‘ + #13#10;
      end else begin
        temp := temp + ‘是否同步执行: False‘ + #13#10;
      end;

      temp := temp + #13#10;
    end;

  finally
    Self.EndRead;
  end;

  Result := Trim( temp );
end;

{ -----------------------------------------------------------------------------}

{ 执行任务线程构造函数}
constructor TExecuteThread.Create( CreateSuspended : Boolean );
begin
  inherited Create( CreateSuspended );
  FreeOnTerminate := true;

  Self.FIsCanTask := false; { 是否可以执行任务默认值为false}
  Self.FIsSynchronize := false; { 是否同步执行默认值为false}
end;

{ 显示线程编号(测试使用)}
procedure TExecuteThread.showThreadID;
begin
  with Form1 do
  begin
    Memo1.Lines.Add( ‘停止执行任务线程编号:‘ + inttostr( Self.ThreadID ) )
  end;

end;

{ 执行任务线程的主方法}
procedure TExecuteThread.Execute;
begin
  while not Terminated do
  begin
    if Terminated then
    begin
      Break;
    end;

    { 判断可以执行任务}
    if Self.FIsCanTask then
    begin
      Self.FProc( ); { 执行任务}
    end;

    { 判断不执行任务}
    if ThreadPool.Instance.DoNextTask( Self ) = false then
    begin

      { 显示执行任务线程编号}
      Synchronize( Self.showThreadID ); { 测试使用,正式使用删除}

      { 判断挂起当前线程}
      if ThreadPool.Instance.IsSuspend( Self ) then
      begin
        Self.Suspend; { 挂起}
      end
      else { 不挂起则终止当前线程}
      begin
        Self.Terminate; { 终止}
      end;
    end;

    { 使界面有反应}
    Application.ProcessMessages;

  end;
end;

{ 设置要执行的任务}
procedure TExecuteThread.StartTask( task : TaskRec );
begin
  Self.FProc := task.TaskProc; { 设置要执行的任务}
  Self.FIsSynchronize := task.isSynchronize; { 设置是否同步执行}
  Self.FIsCanTask := true; { 设置是否可以执行任务为true}
end;

end.

演示例子代码:

unit MainUnit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, System.DateUtils,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class( TForm )
    Button1 : TButton;
    Memo1 : TMemo;
    Button2 : TButton;
    Button3 : TButton;
    Button7 : TButton;
    teskCountEdt : TEdit;
    Button8 : TButton;
    useTimeLab : TLabel;
    Label1 : TLabel;
    procedure Button1Click( Sender : TObject );
    procedure Button7Click( Sender : TObject );
    procedure Button3Click( Sender : TObject );
    procedure FormDestroy( Sender : TObject );
    procedure Button2Click( Sender : TObject );
    procedure Button8Click( Sender : TObject );
  private
    { Private declarations }
  public
    { Public declarations }
    procedure log( lgoInfo : string ); {  log方法 }
  end;

var
  Form1 : TForm1;

  repeatCount : Integer = 0;

  startTime : TDateTime; {  开始时间 }
  useTime : Double; {  用时 }

implementation

{$R *.dfm}

uses ThreadPoolUint;

procedure TaskFun;
var
  count : Integer;
begin

  {  with Form1 do }
  {  begin }

  {  inc(repeatCount); }

  {  Memo1.Lines.Add(FormatDateTime(‘yyyy-mm-dd hh:mm:ss‘, Now) + }
  {  ‘ repeat count-‘ + IntToStr(repeatCount)); }

  {  count := 50000; }

  {  while count > 0 do }
  {  begin }
  {  Dec(count); }
  {  end; }

  {  end; }

  count := 0;
  while count < 100000 do
  begin
    inc( count );
  end;

end;

procedure TForm1.Button1Click( Sender : TObject );
begin
  ThreadPool.Instance( 5, 20 );
  self.log( ‘线程池创建了‘ );
end;

procedure TForm1.Button2Click( Sender : TObject );
var
  task : TaskRec;
  I : Integer;
  timeStr : string;
  posInt : Integer;
begin

  startTime := Now;
  useTimeLab.Caption := ‘0‘;

  {  演示代码开始----------------------- }

  {  循环添加要执行的任务 }

  {  1,添加要执行任务 }
  for I := 0 to StrToInt( teskCountEdt.Text ) - 1 do
  begin

    {  执行任务记录 }
    task.isSynchronize := false;
    task.TaskProc := TaskFun;

    {  添加要执行的任务 }
    ThreadPool.Instance.AddTask( task );
  end;

  {  2,让线程池执行任务 }
  ThreadPool.Instance.ExecuteTask;

  {  演示代码结束----------------------- }

  useTime := MilliSecondSpan( startTime, Now );
  timeStr := FloatToStr( useTime );
  posInt := Pos( ‘.‘, timeStr );
  Delete( timeStr, posInt, Length( timeStr ) - ( posInt - 1 ) );
  useTimeLab.Caption := ‘共用时: ‘ + timeStr + ‘ 毫秒‘;

end;

procedure TForm1.Button3Click( Sender : TObject );
begin
  self.log( ThreadPool.Instance.GetPoolState ); {  显示线程池状态 }
end;

procedure TForm1.Button7Click( Sender : TObject );
begin
  ThreadPool.ReleaseInstance;
  self.log( ‘线程池释放了‘ );
end;

procedure TForm1.Button8Click( Sender : TObject );
begin
  Memo1.Clear;
  repeatCount := 0;
  useTimeLab.Caption := ‘0‘;
end;

procedure TForm1.FormDestroy( Sender : TObject );
begin
  ThreadPool.ReleaseInstance;
end;

procedure TForm1.log( lgoInfo : string );
begin
  Memo1.Lines.Add( ‘‘ );
  Memo1.Lines.Add( FormatDateTime( ‘yyyy-mm-dd hh:mm:ss‘, Now ) + ‘ ‘ +
    trim( lgoInfo ) )
end;

end.

调用线程池的代码是:

//1,定义一个要执行任务的结构

task.isSynchronize := false;//是否同步执行

task.TaskProc := TaskFun;//要执行任务方法

// 2,向线程池添加要执行的任务

ThreadPool.Instance.AddTask(task);

// 3,让线程池执行任务

ThreadPool.Instance.ExecuteTask;

如果您有任何建议,请联系:[email protected] QQ:14667479

时间: 2024-08-03 01:19:16

Delphi ThreadPool 线程池(Delphi2009以上版本适用)的相关文章

浅谈ThreadPool 线程池(引用)

出自:http://www.cnblogs.com/xugang/archive/2010/04/20/1716042.html 浅谈ThreadPool 线程池 相关概念: 线程池可以看做容纳线程的容器: 一个应用程序最多只能有一个线程池: ThreadPool静态类通过QueueUserWorkItem()方法将工作函数排入线程池: 每排入一个工作函数,就相当于请求创建一个线程: 线程池的作用: 线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的操作服务,减少了创建和销毁线程

ThreadPool线程池 小结

ThreadPool类提供一个线程池,该线程池可用于发送工作项.处理异步 I/O.代表其他线程等待以及处理计时器 线程池通过为应用程序提供一个由系统管理的辅助线程池使您可以更为有效地使用线程.一个线程监视排到线程池的若干个等待操作的状态.当一个等待操作完成时,线程池中的一个辅助线程就会执行对应的回调函数 托管线程池中的线程为后台线程,即它们的 IsBackground 属性为 true.这意味着在所有的前台线程都已退出后,ThreadPool 线程不会让应用程序保持运行 也可以将与等待操作不相关

转载【浅谈ThreadPool 线程池】

浅谈ThreadPool 线程池 http://www.cnblogs.com/xugang/archive/2010/04/20/1716042.html

ThreadPool线程池

1.GetMaxThreads,GetMinThreads class Program { static void Main(string[] args) { int workerThreads; int completePortsThreads; ThreadPool.GetMaxThreads(out workerThreads, out completePortsThreads); Console.WriteLine("线程池中最大的线程数{0},线程池中异步IO线程的最大数目{1}&qu

【python】Threadpool线程池任务终止简单示例

需求 加入我们需要处理一串个位数(0~9),奇数时需要循环打印它:偶数则等待对应时长并完成所有任务:0则是错误,但不需要终止任务,可以自定义一些处理. 关键点 定义func函数处理需求 callback处理返回结果,只有偶数和0返回:奇数会一直执行:要控制线程池状态,则需要针对偶数和0时抛出异常,并捕获异常处理. threadpool定义线程池并发 实现 # -*- coding: utf-8 -*-from threadpool import makeRequests, ThreadPooli

ThreadPool 线程池(转)

相关概念: 线程池可以看做容纳线程的容器: 一个应用程序最多只能有一个线程池: ThreadPool静态类通过QueueUserWorkItem()方法将工作函数排入线程池: 每排入一个工作函数,就相当于请求创建一个线程: 线程池的作用: 线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的操作服务,减少了创建和销毁线程所需的时间,从而提高效率. 如果一个线程的时间非常长,就没必要用线程池了(不是不能作长时间操作,而是不宜.),况且我们还不能控制线程池中线程的开始.挂起.和中止.

ThreadPool 线程池的作用

相关概念: 线程池可以看做容纳线程的容器: 一个应用程序最多只能有一个线程池: ThreadPool静态类通过QueueUserWorkItem()方法将工作函数排入线程池: 每排入一个工作函数,就相当于请求创建一个线程: 线程池的作用: 线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的操作服务,减少了创建和销毁线程所需的时间,从而提高效率. 如果一个线程的时间非常长,就没必要用线程池了(不是不能作长时间操作,而是不宜.),况且我们还不能控制线程池中线程的开始.挂起.和中止.

ThreadPool线程池的关注点

public class TestThreadPool { //线程池维护线程的最少数量 private static final int COREPOOLSIZE = 2; //线程池维护线程的最大数量 private static final int MAXINUMPOOLSIZE = 5; //线程池维护线程所允许的空闲时间 private static final long KEEPALIVETIME = 4; //线程池维护线程所允许的空闲时间的单位 private static fi

浅谈ThreadPool 线程池

相关概念: 线程池可以看做容纳线程的容器: 一个应用程序最多只能有一个线程池: ThreadPool静态类通过QueueUserWorkItem()方法将工作函数排入线程池: 每排入一个工作函数,就相当于请求创建一个线程: 线程池的作用: 线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的操作服务,减少了创建和销毁线程所需的时间,从而提高效率. 如果一个线程的时间非常长,就没必要用线程池了(不是不能作长时间操作,而是不宜.),况且我们还不能控制线程池中线程的开始.挂起.和中止.