delphi 自我删除和线程池(1000行代码,需要仔细研究)

[delphi] view plain copy
 
  1. unit Unit4;  
  2.   
  3. interface  
  4.   
  5. uses  
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  7.   Dialogs, StdCtrls, ShellAPI, ShlObj, uThreadPool;  
  8.   
  9. type  
  10.   TForm4 = class(TForm)  
  11.     Button1: TButton;  
  12.     Button2: TButton;  
  13.     Button3: TButton;  
  14.     Button4: TButton;  
  15.     procedure Button1Click(Sender: TObject);  
  16.     procedure FormCreate(Sender: TObject);  
  17.     procedure Button2Click(Sender: TObject);  
  18.     procedure Button3Click(Sender: TObject);  
  19.     procedure Button4Click(Sender: TObject);  
  20.   private  
  21.     { Private declarations }  
  22.   public  
  23.     { Public declarations }  
  24.     procedure MyFun(Sender: TThreadsPool; WorkItem: TWorkItem;  
  25.       aThread: TProcessorThread);  
  26.   end;  
  27.   TRecvCommDataWorkItem=class(TWorkItem)  
  28.   
  29.   end;  
  30.   
  31. function selfdel: Boolean;  
  32. procedure deleteSelf;  
  33.   
  34. var  
  35.   Form4: TForm4;  
  36.   
  37. implementation  
  38.   
  39. {$R *.dfm}  
  40.   
  41. procedure TForm4.Button1Click(Sender: TObject);  
  42.   
  43. var  
  44.   BatchFile: TextFile;  
  45.   BatchFileName: string;  
  46.   ProcessInfo: TProcessInformation;  
  47.   StartUpInfo: TStartupInfo;  
  48. begin  
  49.   BatchFileName := ExtractFilePath(ParamStr(0)) + '_deleteme.bat';  
  50.   AssignFile(BatchFile, BatchFileName);  
  51.   Rewrite(BatchFile);  
  52.   Writeln(BatchFile, ':try');  
  53.   Writeln(BatchFile, 'del "' + ParamStr(0) + '"');  
  54.   Writeln(BatchFile, 'if exist "' + ParamStr(0) + '"' + ' goto try');  
  55.   Writeln(BatchFile, 'del %0');  
  56.   CloseFile(BatchFile);  
  57.   FillChar(StartUpInfo, SizeOf(StartUpInfo), $00);  
  58.   StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;  
  59.   StartUpInfo.wShowWindow := SW_HIDE;  
  60.   if CreateProcess(nil, PChar(BatchFileName), nil, nil, False,  
  61.     IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo) then  
  62.   begin  
  63.     CloseHandle(ProcessInfo.hThread);  
  64.     CloseHandle(ProcessInfo.hProcess);  
  65.   end;  
  66.   Application.Terminate;  
  67. end;  
  68.   
  69. procedure TForm4.Button2Click(Sender: TObject);  
  70. var  
  71.   f: TextFile;  
  72. begin  
  73.   AssignFile(f, '.delme.bat');  
  74.   Rewrite(f);  
  75.   Writeln(f, '@echo off');  
  76.   Writeln(f, ':loop');  
  77.   Writeln(f, 'del "' + Application.ExeName + '"');  
  78.   Writeln(f, 'if exist .file.exe goto loop');  
  79.   Writeln(f, 'del .delme.bat');  
  80.   CloseFile(f);  
  81.   winexec('.delme.bat', SW_HIDE);  
  82.   close;  
  83.   Application.Terminate;  
  84. end;  
  85.   
  86. procedure TForm4.Button3Click(Sender: TObject);  
  87. begin  
  88.   selfdel();  
  89. end;  
  90.   
  91. procedure TForm4.Button4Click(Sender: TObject);  
  92. var  
  93.   FThreadPool: TThreadsPool;  
  94.   AWorkItem: TRecvCommDataWorkItem; // 继承自TWorkItem  
  95. begin  
  96.   // 创建线程池  
  97.   FThreadPool := TThreadsPool.Create(Self); // 创建线程池  
  98.   FThreadPool.ThreadsMin := 5; // 初始工作线程数  
  99.   FThreadPool.ThreadsMax := 50; // 最大允许工作线程数  
  100.   FThreadPool.OnProcessRequest := MyFun; // 线程工作函数(DealwithCommRecvData在工作者线程的Execute方法中被调用)  
  101.   
  102.   // 使用线程池  
  103.   AWorkItem := TRecvCommDataWorkItem.Create;  
  104.   
  105.   FThreadPool.AddRequest(AWorkItem); // 向线程池分配一个任务 end;  
  106.   
  107.   FThreadPool.Free;  
  108. end;  
  109.   
  110. function selfdel: Boolean;  
  111. var  
  112.   sei: TSHELLEXECUTEINFO;  
  113.   szModule: PChar;  
  114.   szComspec: PChar;  
  115.   szParams: PChar;  
  116. begin  
  117.   szModule := AllocMem(MAX_PATH);  
  118.   szComspec := AllocMem(MAX_PATH);  
  119.   szParams := AllocMem(MAX_PATH); // get file path names:  
  120.   if ((GetModuleFileName(0, szModule, MAX_PATH) <> 0) and  
  121.       (GetShortPathName(szModule, szModule, MAX_PATH) <> 0) and  
  122.       (GetEnvironmentVariable('COMSPEC', szComspec, MAX_PATH) <> 0)) then  
  123.   begin // set command shell parameters  
  124.     lstrcpy(szParams, '/c del ');  
  125.     lstrcat(szParams, szModule); // set struct members  
  126.     sei.cbSize := SizeOf(sei);  
  127.     sei.Wnd := 0;  
  128.     sei.lpVerb := 'Open';  
  129.     sei.lpFile := szComspec;  
  130.     sei.lpParameters := szParams;  
  131.     sei.lpDirectory := nil;  
  132.     sei.nShow := SW_HIDE;  
  133.     sei.fMask := SEE_MASK_NOCLOSEPROCESS; // invoke command shell  
  134.     if (ShellExecuteEx(@sei)) then  
  135.     begin // suppress command shell process until program exits  
  136.       SetPriorityClass(sei.hProcess, HIGH_PRIORITY_CLASS);  
  137.       // IDLE_PRIORITY_CLASS);  
  138.       SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);  
  139.       SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);  
  140.       // notify explorer shell of deletion  
  141.       SHChangeNotify(SHCNE_Delete, SHCNF_PATH, szModule, nil);  
  142.       Result := True;  
  143.     end  
  144.     else  
  145.       Result := False;  
  146.   end  
  147.   else  
  148.     Result := False;  
  149. end;  
  150.   
  151. procedure TForm4.FormCreate(Sender: TObject);  
  152. begin  
  153.   // Button1Click(Sender);  
  154.   // Button2Click(Sender);  
  155.   // selfdel();  
  156.   // Application.Terminate;  
  157.   // deleteSelf;  
  158. end;  
  159.   
  160. procedure TForm4.MyFun(Sender: TThreadsPool; WorkItem: TWorkItem;  
  161.   aThread: TProcessorThread);  
  162. var  
  163.   i: Integer;  
  164. begin  
  165.   for i := to 500 do  
  166.   begin  
  167.     Form4.Canvas.Lock;  
  168.     Form4.Canvas.TextOut(10, 10,  
  169.       'threadid=' + IntToStr(GetCurrentThreadId()) + ',' + IntToStr(i));  
  170.     Form4.Canvas.Unlock;  
  171.     Sleep(10);  
  172.   end;  
  173. end;  
  174.   
  175. // http://www.52delphi.com/List.asp?ID=364&Page=3  
  176. procedure deleteSelf;  
  177. var  
  178.   hModule: THandle;  
  179.   szModuleName: array [0 .. MAX_PATH] of char;  
  180.   hKrnl32: THandle;  
  181.   pExitProcess, pdeleteFile, pFreeLibrary, pUnmapViewOfFile: pointer;  
  182.   ExitCode: UINT;  
  183. begin  
  184.   hModule := GetModuleHandle(nil);  
  185.   GetModuleFileName(hModule, szModuleName, SizeOf(szModuleName));  
  186.   hKrnl32 := GetModuleHandle('kernel32');  
  187.   pExitProcess := GetProcAddress(hKrnl32, 'ExitProcess');  
  188.   pdeleteFile := GetProcAddress(hKrnl32, 'deleteFileA');  
  189.   pFreeLibrary := GetProcAddress(hKrnl32, 'FreeLibrary');  
  190.   pUnmapViewOfFile := GetProcAddress(hKrnl32, 'UnmapViewOfFile');  
  191.   ExitCode := system.ExitCode;  
  192.   if ($80000000 and GetVersion()) <> then // Win95, 98, Me  
  193.   asm lea eax, szModuleName  
  194.   push ExitCode  
  195.   push 0  
  196.   push eax  
  197.   push pExitProcess  
  198.   push hModule  
  199.   push pdeleteFile  
  200.   push pFreeLibrary  
  201.   ret  
  202.    end  
  203.   else  
  204.   begin  
  205.     CloseHandle(THandle(4));  
  206.       asm lea eax, szModuleName  
  207.       push ExitCode  
  208.       push 0  
  209.       push eax  
  210.       push pExitProcess  
  211.       push hModule  
  212.       push pdeleteFile  
  213.       push pUnmapViewOfFile  
  214.        ret end  
  215.   end  
  216. end;  
  217.   
  218. end.  
[delphi] view plain copy
 
  1. unit uThreadPool;  
  2.   
  3. {   aPool.AddRequest(TMyRequest.Create(RequestParam1, RequestParam2, ...)); }  
  4.   
  5. interface  
  6. uses  
  7.   Windows,  
  8.   Classes;  
  9.   
  10. // 是否记录日志  
  11. // {$DEFINE NOLOGS}  
  12.   
  13. type  
  14.   TCriticalSection = class(TObject)  
  15.   protected  
  16.     FSection: TRTLCriticalSection;  
  17.   public  
  18.     constructor Create;  
  19.     destructor Destroy; override;  
  20.     // 进入临界区  
  21.     procedure Enter;  
  22.     // 离开临界区  
  23.     procedure Leave;  
  24.     // 尝试进入  
  25.     function TryEnter: Boolean;  
  26.   end;  
  27.   
  28. type  
  29.   // 储存请求数据的基本类  
  30.   TWorkItem = class(TObject)  
  31.   public  
  32.     // 是否有重复任务  
  33.     function IsTheSame(DataObj: TWorkItem): Boolean; virtual;  
  34.     // 如果 NOLOGS 被定义,则禁用。  
  35.     function TextForLog: string; virtual;  
  36.   end;  
  37.   
  38. type  
  39.   TThreadsPool = class;  
  40.   
  41.   //线程状态  
  42.   TThreadState = (tcsInitializing, tcsWaiting, tcsGetting, tcsProcessing,  
  43.     tcsProcessed, tcsTerminating, tcsCheckingDown);  
  44.   // 工作线程仅用于线程池内, 不要直接创建并调用它。  
  45.   TProcessorThread = class(TThread)  
  46.   private  
  47.     // 创建线程时临时的Event对象, 阻塞线程直到初始化完成  
  48.     hInitFinished: THandle;  
  49.     // 初始化出错信息  
  50.     sInitError: string;  
  51.     // 记录日志  
  52.     procedure WriteLog(const Str: string; Level: Integer = 0);  
  53.   protected  
  54.     // 线程临界区同步对像  
  55.     csProcessingDataObject: TCriticalSection;  
  56.     // 平均处理时间  
  57.     FAverageProcessing: Integer;  
  58.     // 等待请求的平均时间  
  59.     FAverageWaitingTime: Integer;  
  60.     // 本线程实例的运行状态  
  61.     FCurState: TThreadState;  
  62.     // 本线程实例所附属的线程池  
  63.     FPool: TThreadsPool;  
  64.     // 当前处理的数据对像。  
  65.     FProcessingDataObject: TWorkItem;  
  66.     // 线程停止 Event, TProcessorThread.Terminate 中开绿灯  
  67.     hThreadTerminated: THandle;  
  68.     uProcessingStart: DWORD;  
  69.     // 开始等待的时间, 通过 GetTickCount 取得。  
  70.     uWaitingStart: DWORD;  
  71.     // 计算平均工作时间  
  72.     function AverageProcessingTime: DWORD;  
  73.     // 计算平均等待时间  
  74.     function AverageWaitingTime: DWORD;  
  75.     procedure Execute; override;  
  76.     function IamCurrentlyProcess(DataObj: TWorkItem): Boolean;  
  77.     // 转换枚举类型的线程状态为字串类型  
  78.     function InfoText: string;  
  79.     // 线程是否长时间处理同一个请求?(已死掉?)  
  80.     function IsDead: Boolean;  
  81.     // 线程是否已完成当成任务  
  82.     function isFinished: Boolean;  
  83.     // 线程是否处于空闲状态  
  84.     function isIdle: Boolean;  
  85.     // 平均值校正计算。  
  86.     function NewAverage(OldAvg, NewVal: Integer): Integer;  
  87.   public  
  88.     Tag: Integer;  
  89.     constructor Create(APool: TThreadsPool);  
  90.     destructor Destroy; override;  
  91.     procedure Terminate;  
  92.   end;  
  93.   
  94.   // 线程初始化时触发的事件  
  95.   TProcessorThreadInitializing = procedure(Sender: TThreadsPool; aThread:  
  96.     TProcessorThread) of object;  
  97.   // 线程结束时触发的事件  
  98.   TProcessorThreadFinalizing = procedure(Sender: TThreadsPool; aThread:  
  99.     TProcessorThread) of object;  
  100.   // 线程处理请求时触发的事件  
  101.   TProcessRequest = procedure(Sender: TThreadsPool; WorkItem: TWorkItem;  
  102.     aThread: TProcessorThread) of object;  
  103.   TEmptyKind = (  
  104.     ekQueueEmpty, //任务被取空后  
  105.     ekProcessingFinished // 最后一个任务处理完毕后  
  106.     );  
  107.   // 任务队列空时触发的事件  
  108.   TQueueEmpty = procedure(Sender: TThreadsPool; EmptyKind: TEmptyKind) of  
  109.     object;  
  110.   
  111.   TThreadsPool = class(TComponent)  
  112.   private  
  113.     csQueueManagment: TCriticalSection;  
  114.     csThreadManagment: TCriticalSection;  
  115.     FProcessRequest: TProcessRequest;  
  116.     FQueue: TList;  
  117.     FQueueEmpty: TQueueEmpty;  
  118.     // 线程超时阀值  
  119.     FThreadDeadTimeout: DWORD;  
  120.     FThreadFinalizing: TProcessorThreadFinalizing;  
  121.     FThreadInitializing: TProcessorThreadInitializing;  
  122.     // 工作中的线程  
  123.     FThreads: TList;  
  124.     // 执行了 terminat 发送退出指令, 正在结束的线程.  
  125.     FThreadsKilling: TList;  
  126.     // 最少, 最大线程数  
  127.     FThreadsMax: Integer;  
  128.     // 最少, 最大线程数  
  129.     FThreadsMin: Integer;  
  130.     // 池平均等待时间  
  131.     function PoolAverageWaitingTime: Integer;  
  132.     procedure WriteLog(const Str: string; Level: Integer = 0);  
  133.   protected  
  134.     FLastGetPoint: Integer;  
  135.     // Semaphore, 统计任务队列  
  136.     hSemRequestCount: THandle;  
  137.     // Waitable timer. 每30触发一次的时间量同步  
  138.     hTimCheckPoolDown: THandle;  
  139.     // 线程池停机(检查并清除空闲线程和死线程)  
  140.     procedure CheckPoolDown;  
  141.     // 清除死线程,并补充不足的工作线程  
  142.     procedure CheckThreadsForGrow;  
  143.     procedure DoProcessed;  
  144.     procedure DoProcessRequest(aDataObj: TWorkItem; aThread: TProcessorThread);  
  145.       virtual;  
  146.     procedure DoQueueEmpty(EmptyKind: TEmptyKind); virtual;  
  147.     procedure DoThreadFinalizing(aThread: TProcessorThread); virtual;  
  148.     // 执行事件  
  149.     procedure DoThreadInitializing(aThread: TProcessorThread); virtual;  
  150.     // 释放 FThreadsKilling 列表中的线程  
  151.     procedure FreeFinishedThreads;  
  152.     // 申请任务  
  153.     procedure GetRequest(out Request: TWorkItem);  
  154.     // 清除死线程  
  155.     procedure KillDeadThreads;  
  156.   public  
  157.     constructor Create(AOwner: TComponent); override;  
  158.     destructor Destroy; override;  
  159.     // 就进行任务是否重复的检查, 检查发现重复就返回 False  
  160.     function AddRequest(aDataObject: TWorkItem; CheckForDoubles: Boolean =  
  161.       False): Boolean; overload;  
  162.     // 转换枚举类型的线程状态为字串类型  
  163.     function InfoText: string;  
  164.   published  
  165.     // 线程处理任务时触发的事件  
  166.     property OnProcessRequest: TProcessRequest read FProcessRequest write  
  167.       FProcessRequest;  
  168.     // 任务列表为空时解发的事件  
  169.     property OnQueueEmpty: TQueueEmpty read FQueueEmpty write FQueueEmpty;  
  170.     // 线程结束时触发的事件  
  171.     property OnThreadFinalizing: TProcessorThreadFinalizing read  
  172.       FThreadFinalizing write FThreadFinalizing;  
  173.     // 线程初始化时触发的事件  
  174.     property OnThreadInitializing: TProcessorThreadInitializing read  
  175.       FThreadInitializing write FThreadInitializing;  
  176.     // 线程超时值(毫秒), 如果处理超时,将视为死线程  
  177.     property ThreadDeadTimeout: DWORD read FThreadDeadTimeout write  
  178.       FThreadDeadTimeout default 0;  
  179.     // 最大线程数  
  180.     property ThreadsMax: Integer read FThreadsMax write FThreadsMax default 1;  
  181.     // 最小线程数  
  182.     property ThreadsMin: Integer read FThreadsMin write FThreadsMin default 0;  
  183.   end;  
  184.   
  185. type  
  186.   //日志记志函数  
  187.   TLogWriteProc = procedure(  
  188.     const Str: string; //日志  
  189.     LogID: Integer = 0;  
  190.     Level: Integer = //Level = 0 - 跟踪信息, 10 - 致命错误  
  191.     );  
  192.   
  193. var  
  194.   WriteLog: TLogWriteProc; // 如果存在实例就写日志  
  195.   
  196. implementation  
  197. uses  
  198.   SysUtils;  
  199.   
  200. // 储存请求数据的基本类  
  201. ********************************** TWorkItem *********************************** 
  202. }  
  203.   
  204. function TWorkItem.IsTheSame(DataObj: TWorkItem): Boolean;  
  205. begin  
  206.   Result := False;  
  207. end; { TWorkItem.IsTheSame }  
  208.   
  209. function TWorkItem.TextForLog: string;  
  210. begin  
  211.   Result := 'Request';  
  212. end; { TWorkItem.TextForLog }  
  213.   
  214. ********************************* TThreadsPool ********************************* 
  215. }  
  216.   
  217. constructor TThreadsPool.Create(AOwner: TComponent);  
  218. var  
  219.   DueTo: Int64;  
  220. begin  
  221. {$IFNDEF NOLOGS}  
  222.   WriteLog('创建线程池', 5);  
  223. {$ENDIF}  
  224.   inherited;  
  225.   csQueueManagment := TCriticalSection.Create;  
  226.   FQueue := TList.Create;  
  227.   csThreadManagment := TCriticalSection.Create;  
  228.   FThreads := TList.Create;  
  229.   FThreadsKilling := TList.Create;  
  230.   FThreadsMin := 0;  
  231.   FThreadsMax := 1;  
  232.   FThreadDeadTimeout := 0;  
  233.   FLastGetPoint := 0;  
  234.   //  
  235.   hSemRequestCount := CreateSemaphore(nil, 0, $7FFFFFFF, nil);  
  236.   
  237.   DueTo := -1;  
  238.   //可等待的定时器(只用于Window NT4或更高)  
  239.   hTimCheckPoolDown := CreateWaitableTimer(nil, False, nil);  
  240.   
  241.   if hTimCheckPoolDown = then // Win9x不支持  
  242.     // In Win9x number of thread will be never decrised  
  243.     hTimCheckPoolDown := CreateEvent(nil, False, False, nil)  
  244.   else  
  245.     SetWaitableTimer(hTimCheckPoolDown, DueTo, 30000, nil, nil, False);  
  246. end; { TThreadsPool.Create }  
  247.   
  248. destructor TThreadsPool.Destroy;  
  249. var  
  250.   n, i: Integer;  
  251.   Handles: array of THandle;  
  252. begin  
  253. {$IFNDEF NOLOGS}  
  254.   WriteLog('线程池销毁', 5);  
  255. {$ENDIF}  
  256.   csThreadManagment.Enter;  
  257.   
  258.   SetLength(Handles, FThreads.Count);  
  259.   n := 0;  
  260.   for i := to FThreads.Count - do  
  261.     if FThreads[i] <> nil then  
  262.     begin  
  263.       Handles[n] := TProcessorThread(FThreads[i]).Handle;  
  264.       TProcessorThread(FThreads[i]).Terminate;  
  265.       Inc(n);  
  266.     end;  
  267.   
  268.   csThreadManagment.Leave;  // lixiaoyu 添加于 2009.1.6,如没有此行代码无法成功释放正在执行中的工作者线程,死锁。  
  269.   
  270.   WaitForMultipleObjects(n, @Handles[0], True, 30000);  // 等待工作者线程执行终止  lixiaoyu 注释于 2009.1.6  
  271.   
  272.   csThreadManagment.Enter;  // lixiaoyu 添加于 2009.1.6 再次进入锁定,并释放资源  
  273.   for i := to FThreads.Count - do  
  274.     TProcessorThread(FThreads[i]).Free;  
  275.   FThreads.Free;  
  276.   FThreadsKilling.Free;  
  277.   csThreadManagment.Free;  
  278.   
  279.   csQueueManagment.Enter;  
  280.   for i := FQueue.Count - downto do  
  281.     TObject(FQueue[i]).Free;  
  282.   FQueue.Free;  
  283.   csQueueManagment.Free;  
  284.   
  285.   CloseHandle(hSemRequestCount);  
  286.   CloseHandle(hTimCheckPoolDown);  
  287.   inherited;  
  288. end; { TThreadsPool.Destroy }  
  289.   
  290. function TThreadsPool.AddRequest(aDataObject: TWorkItem; CheckForDoubles:  
  291.   Boolean = False): Boolean;  
  292. var  
  293.   i: Integer;  
  294. begin  
  295. {$IFNDEF NOLOGS}  
  296.   WriteLog('AddRequest(' + aDataObject.TextForLog + ')', 2);  
  297. {$ENDIF}  
  298.   Result := False;  
  299.   csQueueManagment.Enter;  
  300.   try  
  301.     // 如果 CheckForDoubles = TRUE  
  302.     // 则进行任务是否重复的检查  
  303.     if CheckForDoubles then  
  304.       for i := to FQueue.Count - do  
  305.         if (FQueue[i] <> nil)  
  306.           and aDataObject.IsTheSame(TWorkItem(FQueue[i])) then  
  307.           Exit; // 发现有相同的任务  
  308.   
  309.     csThreadManagment.Enter;  
  310.     try  
  311.       // 清除死线程,并补充不足的工作线程  
  312.       CheckThreadsForGrow;  
  313.   
  314.       // 如果 CheckForDoubles = TRUE  
  315.       // 则检查是否有相同的任务正在处理中  
  316.       if CheckForDoubles then  
  317.         for i := to FThreads.Count - do  
  318.           if TProcessorThread(FThreads[i]).IamCurrentlyProcess(aDataObject) then  
  319.             Exit; // 发现有相同的任务  
  320.   
  321.     finally  
  322.       csThreadManagment.Leave;  
  323.     end;  
  324.   
  325.     //将任务加入队列  
  326.     FQueue.Add(aDataObject);  
  327.   
  328.     //释放一个同步信号量  
  329.     ReleaseSemaphore(hSemRequestCount, 1, nil);  
  330. {$IFNDEF NOLOGS}  
  331.     WriteLog('释放一个同步信号量)', 1);  
  332. {$ENDIF}  
  333.     Result := True;  
  334.   finally  
  335.     csQueueManagment.Leave;  
  336.   end;  
  337. {$IFNDEF NOLOGS}  
  338.   //调试信息  
  339.   WriteLog('增加一个任务(' + aDataObject.TextForLog + ')', 1);  
  340. {$ENDIF}  
  341. end; { TThreadsPool.AddRequest }  
  342.   
  343. 函 数 名:TThreadsPool.CheckPoolDown 
  344. 功能描述:线程池停机(检查并清除空闲线程和死线程) 
  345. 输入参数:无 
  346. 返 回 值: 无 
  347. 创建日期:2006.10.22 11:31 
  348. 修改日期:2006. 
  349. 作    者:Kook 
  350. 附加说明: 
  351. }  
  352.   
  353. procedure TThreadsPool.CheckPoolDown;  
  354. var  
  355.   i: Integer;  
  356. begin  
  357. {$IFNDEF NOLOGS}  
  358.   WriteLog('TThreadsPool.CheckPoolDown', 1);  
  359. {$ENDIF}  
  360.   csThreadManagment.Enter;  
  361.   try  
  362. {$IFNDEF NOLOGS}  
  363.     WriteLog(InfoText, 2);  
  364. {$ENDIF}  
  365.     // 清除死线程  
  366.     KillDeadThreads;  
  367.     // 释放 FThreadsKilling 列表中的线程  
  368.     FreeFinishedThreads;  
  369.   
  370.     // 如果线程空闲,就终止它  
  371.     for i := FThreads.Count - downto FThreadsMin do  
  372.       if TProcessorThread(FThreads[i]).isIdle then  
  373.       begin  
  374.         //发出终止命令  
  375.         TProcessorThread(FThreads[i]).Terminate;  
  376.         //加入待清除队列  
  377.         FThreadsKilling.Add(FThreads[i]);  
  378.         //从工作队列中除名  
  379.         FThreads.Delete(i);  
  380.         //todo: ??  
  381.         Break;  
  382.       end;  
  383.   finally  
  384.     csThreadManagment.Leave;  
  385.   end;  
  386. end; { TThreadsPool.CheckPoolDown }  
  387.   
  388. 函 数 名:TThreadsPool.CheckThreadsForGrow 
  389. 功能描述:清除死线程,并补充不足的工作线程 
  390. 输入参数:无 
  391. 返 回 值: 无 
  392. 创建日期:2006.10.22 11:31 
  393. 修改日期:2006. 
  394. 作    者:Kook 
  395. 附加说明: 
  396. }  
  397.   
  398. procedure TThreadsPool.CheckThreadsForGrow;  
  399. var  
  400.   AvgWait: Integer;  
  401.   i: Integer;  
  402. begin  
  403.   
  404.     New thread created if: 
  405.     新建线程的条件: 
  406.       1. 工作线程数小于最小线程数 
  407.       2. 工作线程数小于最大线程数 and 线程池平均等待时间 < 100ms(系统忙) 
  408.       3. 任务大于工作线程数的4倍 
  409.   }  
  410.   
  411.   csThreadManagment.Enter;  
  412.   try  
  413.     KillDeadThreads;  
  414.     if FThreads.Count < FThreadsMin then  
  415.     begin  
  416. {$IFNDEF NOLOGS}  
  417.       WriteLog('工作线程数小于最小线程数', 4);  
  418. {$ENDIF}  
  419.       for i := FThreads.Count to FThreadsMin - do  
  420.       try  
  421.         FThreads.Add(TProcessorThread.Create(Self));  
  422.       except  
  423.         on e: Exception do  
  424.   
  425.           WriteLog(  
  426.             'TProcessorThread.Create raise: ' + e.ClassName + #13#10#9'Message: '  
  427.             + e.Message,  
  428.             9  
  429.             );  
  430.       end  
  431.     end  
  432.     else if FThreads.Count < FThreadsMax then  
  433.     begin  
  434. {$IFNDEF NOLOGS}  
  435.       WriteLog('工作线程数小于最大线程数 and 线程池平均等待时间 < 100ms', 3);  
  436. {$ENDIF}  
  437.       AvgWait := PoolAverageWaitingTime;  
  438. {$IFNDEF NOLOGS}  
  439.       WriteLog(Format(  
  440.         'FThreads.Count (%d)<FThreadsMax(%d), AvgWait=%d',  
  441.         [FThreads.Count, FThreadsMax, AvgWait]),  
  442.         4  
  443.         );  
  444. {$ENDIF}  
  445.   
  446.       if AvgWait < 100 then  
  447.       try  
  448.         FThreads.Add(TProcessorThread.Create(Self));  
  449.       except  
  450.         on e: Exception do  
  451.           WriteLog(  
  452.             'TProcessorThread.Create raise: ' + e.ClassName +  
  453.             #13#10#9'Message: ' + e.Message,  
  454.             9  
  455.             );  
  456.       end;  
  457.     end;  
  458.   finally  
  459.     csThreadManagment.Leave;  
  460.   end;  
  461. end; { TThreadsPool.CheckThreadsForGrow }  
  462.   
  463. procedure TThreadsPool.DoProcessed;  
  464. var  
  465.   i: Integer;  
  466. begin  
  467.   if (FLastGetPoint < FQueue.Count) then  
  468.     Exit;  
  469.   csThreadManagment.Enter;  
  470.   try  
  471.     for i := to FThreads.Count - do  
  472.       if TProcessorThread(FThreads[i]).FCurState in [tcsProcessing] then  
  473.         Exit;  
  474.   finally  
  475.     csThreadManagment.Leave;  
  476.   end;  
  477.   DoQueueEmpty(ekProcessingFinished);  
  478. end; { TThreadsPool.DoProcessed }  
  479.   
  480. procedure TThreadsPool.DoProcessRequest(aDataObj: TWorkItem; aThread:  
  481.   TProcessorThread);  
  482. begin  
  483.   if Assigned(FProcessRequest) then  
  484.     FProcessRequest(Self, aDataObj, aThread);  
  485. end; { TThreadsPool.DoProcessRequest }  
  486.   
  487. procedure TThreadsPool.DoQueueEmpty(EmptyKind: TEmptyKind);  
  488. begin  
  489.   if Assigned(FQueueEmpty) then  
  490.     FQueueEmpty(Self, EmptyKind);  
  491. end; { TThreadsPool.DoQueueEmpty }  
  492.   
  493. procedure TThreadsPool.DoThreadFinalizing(aThread: TProcessorThread);  
  494. begin  
  495.   if Assigned(FThreadFinalizing) then  
  496.     FThreadFinalizing(Self, aThread);  
  497. end; { TThreadsPool.DoThreadFinalizing }  
  498.   
  499. procedure TThreadsPool.DoThreadInitializing(aThread: TProcessorThread);  
  500. begin  
  501.   if Assigned(FThreadInitializing) then  
  502.     FThreadInitializing(Self, aThread);  
  503. end; { TThreadsPool.DoThreadInitializing }  
  504.   
  505. 函 数 名:TThreadsPool.FreeFinishedThreads 
  506. 功能描述:释放 FThreadsKilling 列表中的线程 
  507. 输入参数:无 
  508. 返 回 值: 无 
  509. 创建日期:2006.10.22 11:34 
  510. 修改日期:2006. 
  511. 作    者:Kook 
  512. 附加说明: 
  513. }  
  514.   
  515. procedure TThreadsPool.FreeFinishedThreads;  
  516. var  
  517.   i: Integer;  
  518. begin  
  519.   if csThreadManagment.TryEnter then  
  520.   try  
  521.     for i := FThreadsKilling.Count - downto do  
  522.       if TProcessorThread(FThreadsKilling[i]).isFinished then  
  523.       begin  
  524.         TProcessorThread(FThreadsKilling[i]).Free;  
  525.         FThreadsKilling.Delete(i);  
  526.       end;  
  527.   finally  
  528.     csThreadManagment.Leave  
  529.   end;  
  530. end; { TThreadsPool.FreeFinishedThreads }  
  531.   
  532. 函 数 名:TThreadsPool.GetRequest 
  533. 功能描述:申请任务 
  534. 输入参数:out Request: TRequestDataObject 
  535. 返 回 值: 无 
  536. 创建日期:2006.10.22 11:34 
  537. 修改日期:2006. 
  538. 作    者:Kook 
  539. 附加说明: 
  540. }  
  541.   
  542. procedure TThreadsPool.GetRequest(out Request: TWorkItem);  
  543. begin  
  544. {$IFNDEF NOLOGS}  
  545.   WriteLog('申请任务', 2);  
  546. {$ENDIF}  
  547.   csQueueManagment.Enter;  
  548.   try  
  549.     //跳过空的队列元素  
  550.     while (FLastGetPoint < FQueue.Count) and (FQueue[FLastGetPoint] = nil) do  
  551.       Inc(FLastGetPoint);  
  552.   
  553.     Assert(FLastGetPoint < FQueue.Count);  
  554.     //压缩队列,清除空元素  
  555.     if (FQueue.Count > 127) and (FLastGetPoint >= (3 * FQueue.Count) div 4) then  
  556.     begin  
  557. {$IFNDEF NOLOGS}  
  558.       WriteLog('FQueue.Pack', 1);  
  559. {$ENDIF}  
  560.       FQueue.Pack;  
  561.       FLastGetPoint := 0;  
  562.     end;  
  563.   
  564.     Request := TWorkItem(FQueue[FLastGetPoint]);  
  565.     FQueue[FLastGetPoint] := nil;  
  566.     inc(FLastGetPoint);  
  567.     if (FLastGetPoint = FQueue.Count) then //如果队列中无任务  
  568.     begin  
  569.   
  570.       DoQueueEmpty(ekQueueEmpty);  
  571.       FQueue.Clear;  
  572.       FLastGetPoint := 0;  
  573.     end;  
  574.   finally  
  575.     csQueueManagment.Leave;  
  576.   end;  
  577. end; { TThreadsPool.GetRequest }  
  578.   
  579. function TThreadsPool.InfoText: string;  
  580. begin  
  581.   Result := '';  
  582.   //end;  
  583.   //{$ELSE}  
  584.   //var  
  585.   //  i: Integer;  
  586.   //begin  
  587.   //  csQueueManagment.Enter;  
  588.   //  csThreadManagment.Enter;  
  589.   //  try  
  590.   //    if (FThreads.Count = 0) and (FThreadsKilling.Count = 1) and  
  591.   //      TProcessorThread(FThreadsKilling[0]).isFinished then  
  592.   //      FreeFinishedThreads;  
  593.   //  
  594.   //    Result := Format(  
  595.   //      'Pool thread: Min=%d, Max=%d, WorkingThreadsCount=%d, TerminatedThreadCount=%d, QueueLength=%d'#13#10,  
  596.   //      [ThreadsMin, ThreadsMax, FThreads.Count, FThreadsKilling.Count,  
  597.   //      FQueue.Count]  
  598.   //        );  
  599.   //    if FThreads.Count > 0 then  
  600.   //      Result := Result + 'Working threads:'#13#10;  
  601.   //    for i := 0 to FThreads.Count - 1 do  
  602.   //      Result := Result + TProcessorThread(FThreads[i]).InfoText + #13#10;  
  603.   //    if FThreadsKilling.Count > 0 then  
  604.   //      Result := Result + 'Terminated threads:'#13#10;  
  605.   //    for i := 0 to FThreadsKilling.Count - 1 do  
  606.   //      Result := Result + TProcessorThread(FThreadsKilling[i]).InfoText + #13#10;  
  607.   //  finally  
  608.   //    csThreadManagment.Leave;  
  609.   //    csQueueManagment.Leave;  
  610.   //  end;  
  611.   //end;  
  612.   //{$ENDIF}  
  613. end; { TThreadsPool.InfoText }  
  614.   
  615. 函 数 名:TThreadsPool.KillDeadThreads 
  616. 功能描述:清除死线程 
  617. 输入参数:无 
  618. 返 回 值: 无 
  619. 创建日期:2006.10.22 11:32 
  620. 修改日期:2006. 
  621. 作    者:Kook 
  622. 附加说明: 
  623. }  
  624.   
  625. procedure TThreadsPool.KillDeadThreads;  
  626. var  
  627.   i: Integer;  
  628. begin  
  629.   // Check for dead threads  
  630.   if csThreadManagment.TryEnter then  
  631.   try  
  632.     for i := to FThreads.Count - do  
  633.       if TProcessorThread(FThreads[i]).IsDead then  
  634.       begin  
  635.         // Dead thread moverd to other list.  
  636.         // New thread created to replace dead one  
  637.         TProcessorThread(FThreads[i]).Terminate;  
  638.         FThreadsKilling.Add(FThreads[i]);  
  639.         try  
  640.           FThreads[i] := TProcessorThread.Create(Self);  
  641.         except  
  642.           on e: Exception do  
  643.           begin  
  644.             FThreads[i] := nil;  
  645. {$IFNDEF NOLOGS}  
  646.             WriteLog(  
  647.               'TProcessorThread.Create raise: ' + e.ClassName +  
  648.               #13#10#9'Message: ' + e.Message,  
  649.               9  
  650.               );  
  651. {$ENDIF}  
  652.           end;  
  653.         end;  
  654.       end;  
  655.   finally  
  656.     csThreadManagment.Leave  
  657.   end;  
  658. end; { TThreadsPool.KillDeadThreads }  
  659.   
  660. function TThreadsPool.PoolAverageWaitingTime: Integer;  
  661. var  
  662.   i: Integer;  
  663. begin  
  664.   Result := 0;  
  665.   if FThreads.Count > then  
  666.   begin  
  667.     for i := to FThreads.Count - do  
  668.       Inc(result, TProcessorThread(FThreads[i]).AverageWaitingTime);  
  669.     Result := Result div FThreads.Count  
  670.   end  
  671.   else  
  672.     Result := 1;  
  673. end; { TThreadsPool.PoolAverageWaitingTime }  
  674.   
  675. procedure TThreadsPool.WriteLog(const Str: string; Level: Integer = 0);  
  676. begin  
  677. {$IFNDEF NOLOGS}  
  678.   uThreadPool.WriteLog(Str, 0, Level);  
  679. {$ENDIF}  
  680. end; { TThreadsPool.WriteLog }  
  681.   
  682. // 工作线程仅用于线程池内, 不要直接创建并调用它。  
  683. ******************************* TProcessorThread ******************************* 
  684. }  
  685.   
  686. constructor TProcessorThread.Create(APool: TThreadsPool);  
  687. begin  
  688.   WriteLog('创建工作线程', 5);  
  689.   inherited Create(True);  
  690.   FPool := aPool;  
  691.   
  692.   FAverageWaitingTime := 1000;  
  693.   FAverageProcessing := 3000;  
  694.   
  695.   sInitError := '';  
  696.   
  697.   各参数的意义如下: 
  698.     
  699.    参数一:填上 nil 即可。 
  700.    参数二:是否采用手动调整灯号。 
  701.    参数三:灯号的起始状态,False 表示红灯。 
  702.    参数四:Event 名称, 对象名称相同的话,会指向同一个对象,所以想要有两个Event对象,便要有两个不同的名称(这名称以字符串来存.为NIL的话系统每次会自己创建一个不同的名字,就是被次创建的都是新的EVENT)。 
  703.    传回值:Event handle。 
  704.   }  
  705.   hInitFinished := CreateEvent(nil, True, False, nil);  
  706.   hThreadTerminated := CreateEvent(nil, True, False, nil);  
  707.   csProcessingDataObject := TCriticalSection.Create;  
  708.   try  
  709.     WriteLog('TProcessorThread.Create::Resume', 3);  
  710.     Resume;  
  711.     //阻塞, 等待初始化完成  
  712.     WaitForSingleObject(hInitFinished, INFINITE);  
  713.     if sInitError <> '' then  
  714.       raise Exception.Create(sInitError);  
  715.   finally  
  716.     CloseHandle(hInitFinished);  
  717.   end;  
  718.   WriteLog('TProcessorThread.Create::Finished', 3);  
  719. end; { TProcessorThread.Create }  
  720.   
  721. destructor TProcessorThread.Destroy;  
  722. begin  
  723.   WriteLog('工作线程销毁', 5);  
  724.   CloseHandle(hThreadTerminated);  
  725.   csProcessingDataObject.Free;  
  726.   inherited;  
  727. end; { TProcessorThread.Destroy }  
  728.   
  729. function TProcessorThread.AverageProcessingTime: DWORD;  
  730. begin  
  731.   if (FCurState in [tcsProcessing]) then  
  732.     Result := NewAverage(FAverageProcessing, GetTickCount - uProcessingStart)  
  733.   else  
  734.     Result := FAverageProcessing  
  735. end; { TProcessorThread.AverageProcessingTime }  
  736.   
  737. function TProcessorThread.AverageWaitingTime: DWORD;  
  738. begin  
  739.   if (FCurState in [tcsWaiting, tcsCheckingDown]) then  
  740.     Result := NewAverage(FAverageWaitingTime, GetTickCount - uWaitingStart)  
  741.   else  
  742.     Result := FAverageWaitingTime  
  743. end; { TProcessorThread.AverageWaitingTime }  
  744.   
  745. procedure TProcessorThread.Execute;  
  746.   
  747. type  
  748.   THandleID = (hidTerminateThread, hidRequest, hidCheckPoolDown);  
  749. var  
  750.   WaitedTime: Integer;  
  751.   Handles: array[THandleID] of THandle;  
  752.   
  753. begin  
  754.   WriteLog('工作线程进常运行', 3);  
  755.   //当前状态:初始化  
  756.   FCurState := tcsInitializing;  
  757.   try  
  758.     //执行外部事件  
  759.     FPool.DoThreadInitializing(Self);  
  760.   except  
  761.     on e: Exception do  
  762.       sInitError := e.Message;  
  763.   end;  
  764.   
  765.   //初始化完成,初始化Event绿灯  
  766.   SetEvent(hInitFinished);  
  767.   
  768.   WriteLog('TProcessorThread.Execute::Initialized', 3);  
  769.   
  770.   //引用线程池的同步 Event  
  771.   Handles[hidTerminateThread] := hThreadTerminated;  
  772.   Handles[hidRequest] := FPool.hSemRequestCount;  
  773.   Handles[hidCheckPoolDown] := FPool.hTimCheckPoolDown;  
  774.   
  775.   //时间戳,  
  776.   //todo: 好像在线程中用 GetTickCount; 会不正常  
  777.   uWaitingStart := GetTickCount;  
  778.   //任务置空  
  779.   FProcessingDataObject := nil;  
  780.   
  781.   //大巡环  
  782.   while not terminated do  
  783.   begin  
  784.     //当前状态:等待  
  785.     FCurState := tcsWaiting;  
  786.     //阻塞线程,使线程休眠  
  787.     case WaitForMultipleObjects(Length(Handles), @Handles, False, INFINITE) -  
  788.       WAIT_OBJECT_0 of  
  789.   
  790.       WAIT_OBJECT_0 + ord(hidTerminateThread):  
  791.         begin  
  792.           WriteLog('TProcessorThread.Execute:: Terminate event signaled ', 5);  
  793.           //当前状态:正在终止线程  
  794.           FCurState := tcsTerminating;  
  795.           //退出大巡环(结束线程)  
  796.           Break;  
  797.         end;  
  798.   
  799.       WAIT_OBJECT_0 + ord(hidRequest):  
  800.         begin  
  801.           WriteLog('TProcessorThread.Execute:: Request semaphore signaled ', 3);  
  802.           //等待的时间  
  803.           WaitedTime := GetTickCount - uWaitingStart;  
  804.           //重新计算平均等待时间  
  805.           FAverageWaitingTime := NewAverage(FAverageWaitingTime, WaitedTime);  
  806.           //当前状态:申请任务  
  807.           FCurState := tcsGetting;  
  808.           //如果等待时间过短,则检查工作线程是否足够  
  809.           if WaitedTime < then  
  810.             FPool.CheckThreadsForGrow;  
  811.           //从线程池的任务队列中得到任务  
  812.           FPool.GetRequest(FProcessingDataObject);  
  813.           //开始处理的时间戳  
  814.           uProcessingStart := GetTickCount;  
  815.           //当前状态:执行任务  
  816.           FCurState := tcsProcessing;  
  817.           try  
  818. {$IFNDEF NOLOGS}  
  819.             WriteLog('Processing: ' + FProcessingDataObject.TextForLog, 2);  
  820. {$ENDIF}  
  821.             //执行任务  
  822.             FPool.DoProcessRequest(FProcessingDataObject, Self);  
  823.           except  
  824.             on e: Exception do  
  825.               WriteLog(  
  826.                 'OnProcessRequest for ' + FProcessingDataObject.TextForLog +  
  827.                 #13#10'raise Exception: ' + e.Message,  
  828.                 8  
  829.                 );  
  830.           end;  
  831.   
  832.           //释放任务对象  
  833.           csProcessingDataObject.Enter;  
  834.           try  
  835.             FProcessingDataObject.Free;  
  836.             FProcessingDataObject := nil;  
  837.           finally  
  838.             csProcessingDataObject.Leave;  
  839.           end;  
  840.           //重新计算  
  841.           FAverageProcessing := NewAverage(FAverageProcessing, GetTickCount -  
  842.             uProcessingStart);  
  843.           //当前状态:执行任务完毕  
  844.           FCurState := tcsProcessed;  
  845.           //执行线程外事件  
  846.           FPool.DoProcessed;  
  847.   
  848.           uWaitingStart := GetTickCount;  
  849.         end;  
  850.       WAIT_OBJECT_0 + ord(hidCheckPoolDown):  
  851.         begin  
  852.           // !!! Never called under Win9x  
  853.           WriteLog('TProcessorThread.Execute:: CheckPoolDown timer signaled ',  
  854.             4);  
  855.           //当前状态:线程池停机(检查并清除空闲线程和死线程)  
  856.           FCurState := tcsCheckingDown;  
  857.           FPool.CheckPoolDown;  
  858.         end;  
  859.     end;  
  860.   end;  
  861.   FCurState := tcsTerminating;  
  862.   
  863.   FPool.DoThreadFinalizing(Self);  
  864. end; { TProcessorThread.Execute }  
  865.   
  866. function TProcessorThread.IamCurrentlyProcess(DataObj: TWorkItem): Boolean;  
  867. begin  
  868.   csProcessingDataObject.Enter;  
  869.   try  
  870.     Result := (FProcessingDataObject <> nil) and  
  871.       DataObj.IsTheSame(FProcessingDataObject);  
  872.   finally  
  873.     csProcessingDataObject.Leave;  
  874.   end;  
  875. end; { TProcessorThread.IamCurrentlyProcess }  
  876.   
  877. function TProcessorThread.InfoText: string;  
  878.   
  879. const  
  880.   ThreadStateNames: array[TThreadState] of string =  
  881.   (  
  882.     'tcsInitializing',  
  883.     'tcsWaiting',  
  884.     'tcsGetting',  
  885.     'tcsProcessing',  
  886.     'tcsProcessed',  
  887.     'tcsTerminating',  
  888.     'tcsCheckingDown'  
  889.     );  
  890.   
  891. begin  
  892. {$IFNDEF NOLOGS}  
  893.   Result := Format(  
  894.     '%5d: %15s, AverageWaitingTime=%6d, AverageProcessingTime=%6d',  
  895.     [ThreadID, ThreadStateNames[FCurState], AverageWaitingTime,  
  896.     AverageProcessingTime]  
  897.       );  
  898.   case FCurState of  
  899.     tcsWaiting:  
  900.       Result := Result + ', WaitingTime=' + IntToStr(GetTickCount -  
  901.         uWaitingStart);  
  902.     tcsProcessing:  
  903.       Result := Result + ', ProcessingTime=' + IntToStr(GetTickCount -  
  904.         uProcessingStart);  
  905.   end;  
  906.   
  907.   csProcessingDataObject.Enter;  
  908.   try  
  909.     if FProcessingDataObject <> nil then  
  910.       Result := Result + ' ' + FProcessingDataObject.TextForLog;  
  911.   finally  
  912.     csProcessingDataObject.Leave;  
  913.   end;  
  914. {$ENDIF}  
  915. end; { TProcessorThread.InfoText }  
  916.   
  917. function TProcessorThread.IsDead: Boolean;  
  918. begin  
  919.   Result :=  
  920.     Terminated or  
  921.     (FPool.ThreadDeadTimeout > 0) and (FCurState = tcsProcessing) and  
  922.     (GetTickCount - uProcessingStart > FPool.ThreadDeadTimeout);  
  923.   if Result then  
  924.     WriteLog('Thread dead', 5);  
  925. end; { TProcessorThread.IsDead }  
  926.   
  927. function TProcessorThread.isFinished: Boolean;  
  928. begin  
  929.   Result := WaitForSingleObject(Handle, 0) = WAIT_OBJECT_0;  
  930. end; { TProcessorThread.isFinished }  
  931.   
  932. function TProcessorThread.isIdle: Boolean;  
  933. begin  
  934.   // 如果线程状态是 tcsWaiting, tcsCheckingDown  
  935.   // 并且 空间时间 > 100ms,  
  936.   // 并且 平均等候任务时间大于平均工作时间的 50%  
  937.   // 则视为空闲。  
  938.   Result :=  
  939.     (FCurState in [tcsWaiting, tcsCheckingDown]) and  
  940.     (AverageWaitingTime > 100) and  
  941.     (AverageWaitingTime * 2 > AverageProcessingTime);  
  942. end; { TProcessorThread.isIdle }  
  943.   
  944. function TProcessorThread.NewAverage(OldAvg, NewVal: Integer): Integer;  
  945. begin  
  946.   Result := (OldAvg * 2 + NewVal) div 3;  
  947. end; { TProcessorThread.NewAverage }  
  948.   
  949. procedure TProcessorThread.Terminate;  
  950. begin  
  951.   WriteLog('TProcessorThread.Terminate', 5);  
  952.   inherited Terminate;  
  953.   SetEvent(hThreadTerminated);  
  954. end; { TProcessorThread.Terminate }  
  955.   
  956. procedure TProcessorThread.WriteLog(const Str: string; Level: Integer = 0);  
  957. begin  
  958. {$IFNDEF NOLOGS}  
  959.   uThreadPool.WriteLog(Str, ThreadID, Level);  
  960. {$ENDIF}  
  961. end; { TProcessorThread.WriteLog }  
  962.   
  963. ******************************* TCriticalSection ******************************* 
  964. }  
  965.   
  966. constructor TCriticalSection.Create;  
  967. begin  
  968.   InitializeCriticalSection(FSection);  
  969. end; { TCriticalSection.Create }  
  970.   
  971. destructor TCriticalSection.Destroy;  
  972. begin  
  973.   DeleteCriticalSection(FSection);  
  974. end; { TCriticalSection.Destroy }  
  975.   
  976. procedure TCriticalSection.Enter;  
  977. begin  
  978.   EnterCriticalSection(FSection);  
  979. end; { TCriticalSection.Enter }  
  980.   
  981. procedure TCriticalSection.Leave;  
  982. begin  
  983.   LeaveCriticalSection(FSection);  
  984. end; { TCriticalSection.Leave }  
  985.   
  986. function TCriticalSection.TryEnter: Boolean;  
  987. begin  
  988.   Result := TryEnterCriticalSection(FSection);  
  989. end; { TCriticalSection.TryEnter }  
  990.   
  991. procedure NoLogs(const Str: string; LogID: Integer = 0; Level: Integer = 0);  
  992. begin  
  993. end;  
  994.   
  995. initialization  
  996.   WriteLog := NoLogs;  
  997. end.  

http://blog.csdn.net/earbao/article/details/46515261

原文地址:https://www.cnblogs.com/findumars/p/5338851.html