线程池_uThreadPool

来源:互联网 发布:java停顿用法 编辑:程序博客网 时间:2024/05/16 07:02
unit uThreadPool;{   aPool.AddRequest(TMyRequest.Create(RequestParam1, RequestParam2, ...)); }interfaceuses  Windows,  Classes;// 是否记录日志// {$DEFINE NOLOGS}type  TCriticalSection = class(TObject)  protected    FSection: TRTLCriticalSection;  public    constructor Create;    destructor Destroy; override;    // 进入临界区    procedure Enter;    // 离开临界区    procedure Leave;    // 尝试进入    function TryEnter: Boolean;  end;type  // 储存请求数据的基本类  TWorkItem = class(TObject)  public    // 是否有重复任务    function IsTheSame(DataObj: TWorkItem): Boolean; virtual;    // 如果 NOLOGS 被定义,则禁用。    function TextForLog: string; virtual;  end;type  TThreadsPool = class;  //线程状态  TThreadState = (tcsInitializing, tcsWaiting, tcsGetting, tcsProcessing,    tcsProcessed, tcsTerminating, tcsCheckingDown);  // 工作线程仅用于线程池内, 不要直接创建并调用它。  TProcessorThread = class(TThread)  private    // 创建线程时临时的Event对象, 阻塞线程直到初始化完成    hInitFinished: THandle;    // 初始化出错信息    sInitError: string;    // 记录日志    procedure WriteLog(const Str: string; Level: Integer = 0);  protected    // 线程临界区同步对像    csProcessingDataObject: TCriticalSection;    // 平均处理时间    FAverageProcessing: Integer;    // 等待请求的平均时间    FAverageWaitingTime: Integer;    // 本线程实例的运行状态    FCurState: TThreadState;    // 本线程实例所附属的线程池    FPool: TThreadsPool;    // 当前处理的数据对像。    FProcessingDataObject: TWorkItem;    // 线程停止 Event, TProcessorThread.Terminate 中开绿灯    hThreadTerminated: THandle;    uProcessingStart: DWORD;    // 开始等待的时间, 通过 GetTickCount 取得。    uWaitingStart: DWORD;    // 计算平均工作时间    function AverageProcessingTime: DWORD;    // 计算平均等待时间    function AverageWaitingTime: DWORD;    procedure Execute; override;    function IamCurrentlyProcess(DataObj: TWorkItem): Boolean;    // 转换枚举类型的线程状态为字串类型    function InfoText: string;    // 线程是否长时间处理同一个请求?(已死掉?)    function IsDead: Boolean;    // 线程是否已完成当成任务    function isFinished: Boolean;    // 线程是否处于空闲状态    function isIdle: Boolean;    // 平均值校正计算。    function NewAverage(OldAvg, NewVal: Integer): Integer;  public    Tag: Integer;    constructor Create(APool: TThreadsPool);    destructor Destroy; override;    procedure Terminate;  end;  // 线程初始化时触发的事件  TProcessorThreadInitializing = procedure(Sender: TThreadsPool; aThread:    TProcessorThread) of object;  // 线程结束时触发的事件  TProcessorThreadFinalizing = procedure(Sender: TThreadsPool; aThread:    TProcessorThread) of object;  // 线程处理请求时触发的事件  TProcessRequest = procedure(Sender: TThreadsPool; WorkItem: TWorkItem;    aThread: TProcessorThread) of object;  TEmptyKind = (    ekQueueEmpty, //任务被取空后    ekProcessingFinished // 最后一个任务处理完毕后    );  // 任务队列空时触发的事件  TQueueEmpty = procedure(Sender: TThreadsPool; EmptyKind: TEmptyKind) of    object;  TThreadsPool = class(TComponent)  private    csQueueManagment: TCriticalSection;    csThreadManagment: TCriticalSection;    FProcessRequest: TProcessRequest;    FQueue: TList;    FQueueEmpty: TQueueEmpty;    // 线程超时阀值    FThreadDeadTimeout: DWORD;    FThreadFinalizing: TProcessorThreadFinalizing;    FThreadInitializing: TProcessorThreadInitializing;    // 工作中的线程    FThreads: TList;    // 执行了 terminat 发送退出指令, 正在结束的线程.    FThreadsKilling: TList;    // 最少, 最大线程数    FThreadsMax: Integer;    // 最少, 最大线程数    FThreadsMin: Integer;    // 池平均等待时间    function PoolAverageWaitingTime: Integer;    procedure WriteLog(const Str: string; Level: Integer = 0);  protected    FLastGetPoint: Integer;    // Semaphore, 统计任务队列    hSemRequestCount: THandle;    // Waitable timer. 每30触发一次的时间量同步    hTimCheckPoolDown: THandle;    // 线程池停机(检查并清除空闲线程和死线程)    procedure CheckPoolDown;    // 清除死线程,并补充不足的工作线程    procedure CheckThreadsForGrow;    procedure DoProcessed;    procedure DoProcessRequest(aDataObj: TWorkItem; aThread: TProcessorThread);      virtual;    procedure DoQueueEmpty(EmptyKind: TEmptyKind); virtual;    procedure DoThreadFinalizing(aThread: TProcessorThread); virtual;    // 执行事件    procedure DoThreadInitializing(aThread: TProcessorThread); virtual;    // 释放 FThreadsKilling 列表中的线程    procedure FreeFinishedThreads;    // 申请任务    procedure GetRequest(out Request: TWorkItem);    // 清除死线程    procedure KillDeadThreads;  public    constructor Create(AOwner: TComponent); override;    destructor Destroy; override;    // 就进行任务是否重复的检查, 检查发现重复就返回 False    function AddRequest(aDataObject: TWorkItem; CheckForDoubles: Boolean =      False): Boolean; overload;    // 转换枚举类型的线程状态为字串类型    function InfoText: string;  published    // 线程处理任务时触发的事件    property OnProcessRequest: TProcessRequest read FProcessRequest write      FProcessRequest;    // 任务列表为空时解发的事件    property OnQueueEmpty: TQueueEmpty read FQueueEmpty write FQueueEmpty;    // 线程结束时触发的事件    property OnThreadFinalizing: TProcessorThreadFinalizing read      FThreadFinalizing write FThreadFinalizing;    // 线程初始化时触发的事件    property OnThreadInitializing: TProcessorThreadInitializing read      FThreadInitializing write FThreadInitializing;    // 线程超时值(毫秒), 如果处理超时,将视为死线程    property ThreadDeadTimeout: DWORD read FThreadDeadTimeout write      FThreadDeadTimeout default 0;    // 最大线程数    property ThreadsMax: Integer read FThreadsMax write FThreadsMax default 1;    // 最小线程数    property ThreadsMin: Integer read FThreadsMin write FThreadsMin default 0;  end;type  //日志记志函数  TLogWriteProc = procedure(    const Str: string; //日志    LogID: Integer = 0;    Level: Integer = 0 //Level = 0 - 跟踪信息, 10 - 致命错误    );var  WriteLog: TLogWriteProc; // 如果存在实例就写日志implementationuses  SysUtils;// 储存请求数据的基本类{********************************** TWorkItem ***********************************}function TWorkItem.IsTheSame(DataObj: TWorkItem): Boolean;begin  Result := False;end; { TWorkItem.IsTheSame }function TWorkItem.TextForLog: string;begin  Result := 'Request';end; { TWorkItem.TextForLog }{********************************* TThreadsPool *********************************}constructor TThreadsPool.Create(AOwner: TComponent);var  DueTo: Int64;begin{$IFNDEF NOLOGS}  WriteLog('创建线程池', 5);{$ENDIF}  inherited;  csQueueManagment := TCriticalSection.Create;  FQueue := TList.Create;  csThreadManagment := TCriticalSection.Create;  FThreads := TList.Create;  FThreadsKilling := TList.Create;  FThreadsMin := 0;  FThreadsMax := 1;  FThreadDeadTimeout := 0;  FLastGetPoint := 0;  //  hSemRequestCount := CreateSemaphore(nil, 0, $7FFFFFFF, nil);  DueTo := -1;  //可等待的定时器(只用于Window NT4或更高)  hTimCheckPoolDown := CreateWaitableTimer(nil, False, nil);  if hTimCheckPoolDown = 0 then // Win9x不支持    // In Win9x number of thread will be never decrised    hTimCheckPoolDown := CreateEvent(nil, False, False, nil)  else    SetWaitableTimer(hTimCheckPoolDown, DueTo, 30000, nil, nil, False);end; { TThreadsPool.Create }destructor TThreadsPool.Destroy;var  n, i: Integer;  Handles: array of THandle;begin{$IFNDEF NOLOGS}  WriteLog('线程池销毁', 5);{$ENDIF}  csThreadManagment.Enter;  SetLength(Handles, FThreads.Count);  n := 0;  for i := 0 to FThreads.Count - 1 do    if FThreads[i] <> nil then    begin      Handles[n] := TProcessorThread(FThreads[i]).Handle;      TProcessorThread(FThreads[i]).Terminate;      Inc(n);    end;  csThreadManagment.Leave;  // lixiaoyu 添加于 2009.1.6,如没有此行代码无法成功释放正在执行中的工作者线程,死锁。  WaitForMultipleObjects(n, @Handles[0], True, 30000);  // 等待工作者线程执行终止  lixiaoyu 注释于 2009.1.6  csThreadManagment.Enter;  // lixiaoyu 添加于 2009.1.6 再次进入锁定,并释放资源  for i := 0 to FThreads.Count - 1 do    TProcessorThread(FThreads[i]).Free;  FThreads.Free;  FThreadsKilling.Free;  csThreadManagment.Free;  csQueueManagment.Enter;  for i := FQueue.Count - 1 downto 0 do    TObject(FQueue[i]).Free;  FQueue.Free;  csQueueManagment.Free;  CloseHandle(hSemRequestCount);  CloseHandle(hTimCheckPoolDown);  inherited;end; { TThreadsPool.Destroy }function TThreadsPool.AddRequest(aDataObject: TWorkItem; CheckForDoubles:  Boolean = False): Boolean;var  i: Integer;begin{$IFNDEF NOLOGS}  WriteLog('AddRequest(' + aDataObject.TextForLog + ')', 2);{$ENDIF}  Result := False;  csQueueManagment.Enter;  try    // 如果 CheckForDoubles = TRUE    // 则进行任务是否重复的检查    if CheckForDoubles then      for i := 0 to FQueue.Count - 1 do        if (FQueue[i] <> nil)          and aDataObject.IsTheSame(TWorkItem(FQueue[i])) then          Exit; // 发现有相同的任务    csThreadManagment.Enter;    try      // 清除死线程,并补充不足的工作线程      CheckThreadsForGrow;      // 如果 CheckForDoubles = TRUE      // 则检查是否有相同的任务正在处理中      if CheckForDoubles then        for i := 0 to FThreads.Count - 1 do          if TProcessorThread(FThreads[i]).IamCurrentlyProcess(aDataObject) then            Exit; // 发现有相同的任务    finally      csThreadManagment.Leave;    end;    //将任务加入队列    FQueue.Add(aDataObject);    //释放一个同步信号量    ReleaseSemaphore(hSemRequestCount, 1, nil);{$IFNDEF NOLOGS}    WriteLog('释放一个同步信号量)', 1);{$ENDIF}    Result := True;  finally    csQueueManagment.Leave;  end;{$IFNDEF NOLOGS}  //调试信息  WriteLog('增加一个任务(' + aDataObject.TextForLog + ')', 1);{$ENDIF}end; { TThreadsPool.AddRequest }{函 数 名:TThreadsPool.CheckPoolDown功能描述:线程池停机(检查并清除空闲线程和死线程)输入参数:无返 回 值: 无创建日期:2006.10.22 11:31修改日期:2006.作    者:Kook附加说明:}procedure TThreadsPool.CheckPoolDown;var  i: Integer;begin{$IFNDEF NOLOGS}  WriteLog('TThreadsPool.CheckPoolDown', 1);{$ENDIF}  csThreadManagment.Enter;  try{$IFNDEF NOLOGS}    WriteLog(InfoText, 2);{$ENDIF}    // 清除死线程    KillDeadThreads;    // 释放 FThreadsKilling 列表中的线程    FreeFinishedThreads;    // 如果线程空闲,就终止它    for i := FThreads.Count - 1 downto FThreadsMin do      if TProcessorThread(FThreads[i]).isIdle then      begin        //发出终止命令        TProcessorThread(FThreads[i]).Terminate;        //加入待清除队列        FThreadsKilling.Add(FThreads[i]);        //从工作队列中除名        FThreads.Delete(i);        //todo: ??        Break;      end;  finally    csThreadManagment.Leave;  end;end; { TThreadsPool.CheckPoolDown }{函 数 名:TThreadsPool.CheckThreadsForGrow功能描述:清除死线程,并补充不足的工作线程输入参数:无返 回 值: 无创建日期:2006.10.22 11:31修改日期:2006.作    者:Kook附加说明:}procedure TThreadsPool.CheckThreadsForGrow;var  AvgWait: Integer;  i: Integer;begin  {    New thread created if:    新建线程的条件:      1. 工作线程数小于最小线程数      2. 工作线程数小于最大线程数 and 线程池平均等待时间 < 100ms(系统忙)      3. 任务大于工作线程数的4倍  }  csThreadManagment.Enter;  try    KillDeadThreads;    if FThreads.Count < FThreadsMin then    begin{$IFNDEF NOLOGS}      WriteLog('工作线程数小于最小线程数', 4);{$ENDIF}      for i := FThreads.Count to FThreadsMin - 1 do      try        FThreads.Add(TProcessorThread.Create(Self));      except        on e: Exception do          WriteLog(            'TProcessorThread.Create raise: ' + e.ClassName + #13#10#9'Message: '            + e.Message,            9            );      end    end    else if FThreads.Count < FThreadsMax then    begin{$IFNDEF NOLOGS}      WriteLog('工作线程数小于最大线程数 and 线程池平均等待时间 < 100ms', 3);{$ENDIF}      AvgWait := PoolAverageWaitingTime;{$IFNDEF NOLOGS}      WriteLog(Format(        'FThreads.Count (%d)<FThreadsMax(%d), AvgWait=%d',        [FThreads.Count, FThreadsMax, AvgWait]),        4        );{$ENDIF}      if AvgWait < 100 then      try        FThreads.Add(TProcessorThread.Create(Self));      except        on e: Exception do          WriteLog(            'TProcessorThread.Create raise: ' + e.ClassName +            #13#10#9'Message: ' + e.Message,            9            );      end;    end;  finally    csThreadManagment.Leave;  end;end; { TThreadsPool.CheckThreadsForGrow }procedure TThreadsPool.DoProcessed;var  i: Integer;begin  if (FLastGetPoint < FQueue.Count) then    Exit;  csThreadManagment.Enter;  try    for i := 0 to FThreads.Count - 1 do      if TProcessorThread(FThreads[i]).FCurState in [tcsProcessing] then        Exit;  finally    csThreadManagment.Leave;  end;  DoQueueEmpty(ekProcessingFinished);end; { TThreadsPool.DoProcessed }procedure TThreadsPool.DoProcessRequest(aDataObj: TWorkItem; aThread:  TProcessorThread);begin  if Assigned(FProcessRequest) then    FProcessRequest(Self, aDataObj, aThread);end; { TThreadsPool.DoProcessRequest }procedure TThreadsPool.DoQueueEmpty(EmptyKind: TEmptyKind);begin  if Assigned(FQueueEmpty) then    FQueueEmpty(Self, EmptyKind);end; { TThreadsPool.DoQueueEmpty }procedure TThreadsPool.DoThreadFinalizing(aThread: TProcessorThread);begin  if Assigned(FThreadFinalizing) then    FThreadFinalizing(Self, aThread);end; { TThreadsPool.DoThreadFinalizing }procedure TThreadsPool.DoThreadInitializing(aThread: TProcessorThread);begin  if Assigned(FThreadInitializing) then    FThreadInitializing(Self, aThread);end; { TThreadsPool.DoThreadInitializing }{函 数 名:TThreadsPool.FreeFinishedThreads功能描述:释放 FThreadsKilling 列表中的线程输入参数:无返 回 值: 无创建日期:2006.10.22 11:34修改日期:2006.作    者:Kook附加说明:}procedure TThreadsPool.FreeFinishedThreads;var  i: Integer;begin  if csThreadManagment.TryEnter then  try    for i := FThreadsKilling.Count - 1 downto 0 do      if TProcessorThread(FThreadsKilling[i]).isFinished then      begin        TProcessorThread(FThreadsKilling[i]).Free;        FThreadsKilling.Delete(i);      end;  finally    csThreadManagment.Leave  end;end; { TThreadsPool.FreeFinishedThreads }{函 数 名:TThreadsPool.GetRequest功能描述:申请任务输入参数:out Request: TRequestDataObject返 回 值: 无创建日期:2006.10.22 11:34修改日期:2006.作    者:Kook附加说明:}procedure TThreadsPool.GetRequest(out Request: TWorkItem);begin{$IFNDEF NOLOGS}  WriteLog('申请任务', 2);{$ENDIF}  csQueueManagment.Enter;  try    //跳过空的队列元素    while (FLastGetPoint < FQueue.Count) and (FQueue[FLastGetPoint] = nil) do      Inc(FLastGetPoint);    Assert(FLastGetPoint < FQueue.Count);    //压缩队列,清除空元素    if (FQueue.Count > 127) and (FLastGetPoint >= (3 * FQueue.Count) div 4) then    begin{$IFNDEF NOLOGS}      WriteLog('FQueue.Pack', 1);{$ENDIF}      FQueue.Pack;      FLastGetPoint := 0;    end;    Request := TWorkItem(FQueue[FLastGetPoint]);    FQueue[FLastGetPoint] := nil;    inc(FLastGetPoint);    if (FLastGetPoint = FQueue.Count) then //如果队列中无任务    begin      DoQueueEmpty(ekQueueEmpty);      FQueue.Clear;      FLastGetPoint := 0;    end;  finally    csQueueManagment.Leave;  end;end; { TThreadsPool.GetRequest }function TThreadsPool.InfoText: string;begin  Result := '';  //end;  //{$ELSE}  //var  //  i: Integer;  //begin  //  csQueueManagment.Enter;  //  csThreadManagment.Enter;  //  try  //    if (FThreads.Count = 0) and (FThreadsKilling.Count = 1) and  //      TProcessorThread(FThreadsKilling[0]).isFinished then  //      FreeFinishedThreads;  //  //    Result := Format(  //      'Pool thread: Min=%d, Max=%d, WorkingThreadsCount=%d, TerminatedThreadCount=%d, QueueLength=%d'#13#10,  //      [ThreadsMin, ThreadsMax, FThreads.Count, FThreadsKilling.Count,  //      FQueue.Count]  //        );  //    if FThreads.Count > 0 then  //      Result := Result + 'Working threads:'#13#10;  //    for i := 0 to FThreads.Count - 1 do  //      Result := Result + TProcessorThread(FThreads[i]).InfoText + #13#10;  //    if FThreadsKilling.Count > 0 then  //      Result := Result + 'Terminated threads:'#13#10;  //    for i := 0 to FThreadsKilling.Count - 1 do  //      Result := Result + TProcessorThread(FThreadsKilling[i]).InfoText + #13#10;  //  finally  //    csThreadManagment.Leave;  //    csQueueManagment.Leave;  //  end;  //end;  //{$ENDIF}end; { TThreadsPool.InfoText }{函 数 名:TThreadsPool.KillDeadThreads功能描述:清除死线程输入参数:无返 回 值: 无创建日期:2006.10.22 11:32修改日期:2006.作    者:Kook附加说明:}procedure TThreadsPool.KillDeadThreads;var  i: Integer;begin  // Check for dead threads  if csThreadManagment.TryEnter then  try    for i := 0 to FThreads.Count - 1 do      if TProcessorThread(FThreads[i]).IsDead then      begin        // Dead thread moverd to other list.        // New thread created to replace dead one        TProcessorThread(FThreads[i]).Terminate;        FThreadsKilling.Add(FThreads[i]);        try          FThreads[i] := TProcessorThread.Create(Self);        except          on e: Exception do          begin            FThreads[i] := nil;{$IFNDEF NOLOGS}            WriteLog(              'TProcessorThread.Create raise: ' + e.ClassName +              #13#10#9'Message: ' + e.Message,              9              );{$ENDIF}          end;        end;      end;  finally    csThreadManagment.Leave  end;end; { TThreadsPool.KillDeadThreads }function TThreadsPool.PoolAverageWaitingTime: Integer;var  i: Integer;begin  Result := 0;  if FThreads.Count > 0 then  begin    for i := 0 to FThreads.Count - 1 do      Inc(result, TProcessorThread(FThreads[i]).AverageWaitingTime);    Result := Result div FThreads.Count  end  else    Result := 1;end; { TThreadsPool.PoolAverageWaitingTime }procedure TThreadsPool.WriteLog(const Str: string; Level: Integer = 0);begin{$IFNDEF NOLOGS}  uThreadPool.WriteLog(Str, 0, Level);{$ENDIF}end; { TThreadsPool.WriteLog }// 工作线程仅用于线程池内, 不要直接创建并调用它。{******************************* TProcessorThread *******************************}constructor TProcessorThread.Create(APool: TThreadsPool);begin  WriteLog('创建工作线程', 5);  inherited Create(True);  FPool := aPool;  FAverageWaitingTime := 1000;  FAverageProcessing := 3000;  sInitError := '';  {  各参数的意义如下:      参数一:填上 nil 即可。   参数二:是否采用手动调整灯号。   参数三:灯号的起始状态,False 表示红灯。   参数四:Event 名称, 对象名称相同的话,会指向同一个对象,所以想要有两个Event对象,便要有两个不同的名称(这名称以字符串来存.为NIL的话系统每次会自己创建一个不同的名字,就是被次创建的都是新的EVENT)。   传回值:Event handle。  }  hInitFinished := CreateEvent(nil, True, False, nil);  hThreadTerminated := CreateEvent(nil, True, False, nil);  csProcessingDataObject := TCriticalSection.Create;  try    WriteLog('TProcessorThread.Create::Resume', 3);    Resume;    //阻塞, 等待初始化完成    WaitForSingleObject(hInitFinished, INFINITE);    if sInitError <> '' then      raise Exception.Create(sInitError);  finally    CloseHandle(hInitFinished);  end;  WriteLog('TProcessorThread.Create::Finished', 3);end; { TProcessorThread.Create }destructor TProcessorThread.Destroy;begin  WriteLog('工作线程销毁', 5);  CloseHandle(hThreadTerminated);  csProcessingDataObject.Free;  inherited;end; { TProcessorThread.Destroy }function TProcessorThread.AverageProcessingTime: DWORD;begin  if (FCurState in [tcsProcessing]) then    Result := NewAverage(FAverageProcessing, GetTickCount - uProcessingStart)  else    Result := FAverageProcessingend; { TProcessorThread.AverageProcessingTime }function TProcessorThread.AverageWaitingTime: DWORD;begin  if (FCurState in [tcsWaiting, tcsCheckingDown]) then    Result := NewAverage(FAverageWaitingTime, GetTickCount - uWaitingStart)  else    Result := FAverageWaitingTimeend; { TProcessorThread.AverageWaitingTime }procedure TProcessorThread.Execute;type  THandleID = (hidTerminateThread, hidRequest, hidCheckPoolDown);var  WaitedTime: Integer;  Handles: array[THandleID] of THandle;begin  WriteLog('工作线程进常运行', 3);  //当前状态:初始化  FCurState := tcsInitializing;  try    //执行外部事件    FPool.DoThreadInitializing(Self);  except    on e: Exception do      sInitError := e.Message;  end;  //初始化完成,初始化Event绿灯  SetEvent(hInitFinished);  WriteLog('TProcessorThread.Execute::Initialized', 3);  //引用线程池的同步 Event  Handles[hidTerminateThread] := hThreadTerminated;  Handles[hidRequest] := FPool.hSemRequestCount;  Handles[hidCheckPoolDown] := FPool.hTimCheckPoolDown;  //时间戳,  //todo: 好像在线程中用 GetTickCount; 会不正常  uWaitingStart := GetTickCount;  //任务置空  FProcessingDataObject := nil;  //大巡环  while not terminated do  begin    //当前状态:等待    FCurState := tcsWaiting;    //阻塞线程,使线程休眠    case WaitForMultipleObjects(Length(Handles), @Handles, False, INFINITE) -      WAIT_OBJECT_0 of      WAIT_OBJECT_0 + ord(hidTerminateThread):        begin          WriteLog('TProcessorThread.Execute:: Terminate event signaled ', 5);          //当前状态:正在终止线程          FCurState := tcsTerminating;          //退出大巡环(结束线程)          Break;        end;      WAIT_OBJECT_0 + ord(hidRequest):        begin          WriteLog('TProcessorThread.Execute:: Request semaphore signaled ', 3);          //等待的时间          WaitedTime := GetTickCount - uWaitingStart;          //重新计算平均等待时间          FAverageWaitingTime := NewAverage(FAverageWaitingTime, WaitedTime);          //当前状态:申请任务          FCurState := tcsGetting;          //如果等待时间过短,则检查工作线程是否足够          if WaitedTime < 5 then            FPool.CheckThreadsForGrow;          //从线程池的任务队列中得到任务          FPool.GetRequest(FProcessingDataObject);          //开始处理的时间戳          uProcessingStart := GetTickCount;          //当前状态:执行任务          FCurState := tcsProcessing;          try{$IFNDEF NOLOGS}            WriteLog('Processing: ' + FProcessingDataObject.TextForLog, 2);{$ENDIF}            //执行任务            FPool.DoProcessRequest(FProcessingDataObject, Self);          except            on e: Exception do              WriteLog(                'OnProcessRequest for ' + FProcessingDataObject.TextForLog +                #13#10'raise Exception: ' + e.Message,                8                );          end;          //释放任务对象          csProcessingDataObject.Enter;          try            FProcessingDataObject.Free;            FProcessingDataObject := nil;          finally            csProcessingDataObject.Leave;          end;          //重新计算          FAverageProcessing := NewAverage(FAverageProcessing, GetTickCount -            uProcessingStart);          //当前状态:执行任务完毕          FCurState := tcsProcessed;          //执行线程外事件          FPool.DoProcessed;          uWaitingStart := GetTickCount;        end;      WAIT_OBJECT_0 + ord(hidCheckPoolDown):        begin          // !!! Never called under Win9x          WriteLog('TProcessorThread.Execute:: CheckPoolDown timer signaled ',            4);          //当前状态:线程池停机(检查并清除空闲线程和死线程)          FCurState := tcsCheckingDown;          FPool.CheckPoolDown;        end;    end;  end;  FCurState := tcsTerminating;  FPool.DoThreadFinalizing(Self);end; { TProcessorThread.Execute }function TProcessorThread.IamCurrentlyProcess(DataObj: TWorkItem): Boolean;begin  csProcessingDataObject.Enter;  try    Result := (FProcessingDataObject <> nil) and      DataObj.IsTheSame(FProcessingDataObject);  finally    csProcessingDataObject.Leave;  end;end; { TProcessorThread.IamCurrentlyProcess }function TProcessorThread.InfoText: string;const  ThreadStateNames: array[TThreadState] of string =  (    'tcsInitializing',    'tcsWaiting',    'tcsGetting',    'tcsProcessing',    'tcsProcessed',    'tcsTerminating',    'tcsCheckingDown'    );begin{$IFNDEF NOLOGS}  Result := Format(    '%5d: %15s, AverageWaitingTime=%6d, AverageProcessingTime=%6d',    [ThreadID, ThreadStateNames[FCurState], AverageWaitingTime,    AverageProcessingTime]      );  case FCurState of    tcsWaiting:      Result := Result + ', WaitingTime=' + IntToStr(GetTickCount -        uWaitingStart);    tcsProcessing:      Result := Result + ', ProcessingTime=' + IntToStr(GetTickCount -        uProcessingStart);  end;  csProcessingDataObject.Enter;  try    if FProcessingDataObject <> nil then      Result := Result + ' ' + FProcessingDataObject.TextForLog;  finally    csProcessingDataObject.Leave;  end;{$ENDIF}end; { TProcessorThread.InfoText }function TProcessorThread.IsDead: Boolean;begin  Result :=    Terminated or    (FPool.ThreadDeadTimeout > 0) and (FCurState = tcsProcessing) and    (GetTickCount - uProcessingStart > FPool.ThreadDeadTimeout);  if Result then    WriteLog('Thread dead', 5);end; { TProcessorThread.IsDead }function TProcessorThread.isFinished: Boolean;begin  Result := WaitForSingleObject(Handle, 0) = WAIT_OBJECT_0;end; { TProcessorThread.isFinished }function TProcessorThread.isIdle: Boolean;begin  // 如果线程状态是 tcsWaiting, tcsCheckingDown  // 并且 空间时间 > 100ms,  // 并且 平均等候任务时间大于平均工作时间的 50%  // 则视为空闲。  Result :=    (FCurState in [tcsWaiting, tcsCheckingDown]) and    (AverageWaitingTime > 100) and    (AverageWaitingTime * 2 > AverageProcessingTime);end; { TProcessorThread.isIdle }function TProcessorThread.NewAverage(OldAvg, NewVal: Integer): Integer;begin  Result := (OldAvg * 2 + NewVal) div 3;end; { TProcessorThread.NewAverage }procedure TProcessorThread.Terminate;begin  WriteLog('TProcessorThread.Terminate', 5);  inherited Terminate;  SetEvent(hThreadTerminated);end; { TProcessorThread.Terminate }procedure TProcessorThread.WriteLog(const Str: string; Level: Integer = 0);begin{$IFNDEF NOLOGS}  uThreadPool.WriteLog(Str, ThreadID, Level);{$ENDIF}end; { TProcessorThread.WriteLog }{******************************* TCriticalSection *******************************}constructor TCriticalSection.Create;begin  InitializeCriticalSection(FSection);end; { TCriticalSection.Create }destructor TCriticalSection.Destroy;begin  DeleteCriticalSection(FSection);end; { TCriticalSection.Destroy }procedure TCriticalSection.Enter;begin  EnterCriticalSection(FSection);end; { TCriticalSection.Enter }procedure TCriticalSection.Leave;begin  LeaveCriticalSection(FSection);end; { TCriticalSection.Leave }function TCriticalSection.TryEnter: Boolean;begin  Result := TryEnterCriticalSection(FSection);end; { TCriticalSection.TryEnter }procedure NoLogs(const Str: string; LogID: Integer = 0; Level: Integer = 0);beginend;initialization  WriteLog := NoLogs;end.

0 0
原创粉丝点击