本文整理自网络,侵删。
//******************************************************************************//线程池//******************************************************************************//作者:Cai//日期:2011-3-10//******************************************************************************unit ThreadPoolClass;
interfaceusesWindows, Classes, SyncObjectClass;
typeTThreadPool = class;
TOnTerminateTask = procedure (Sender: TObject) of object;TTaskObject = class(TObject)privateFOwner: TThread;FOnTerminateTask: TOnTerminateTask;FThreadID: Cardinal;FTaskID : Cardinal;procedure SetOnTerminateTask(const Value: TOnTerminateTask);protectedprocedure Execute();virtual; abstract;procedure WaitFor(iTimeOut: Cardinal);virtual;procedure Terminate;publicconstructor Create();virtual;destructor Destroy();override;procedure Synchronize(AMethod: TThreadMethod);property ThreadID:Cardinal read FThreadID;property TaskID:Cardinal read FTaskID;property OnTerminateTask: TOnTerminateTask read FOnTerminateTask write SetOnTerminateTask;end;
TThreadPolicyInt = 0..6;
TOnTerminatingTask = procedure(Sender: TObject; TaskObject: TTaskObject) of object;
TThreadPool = class(TObject)privateFCriticalSectionLocker: TCriticalSectionLocker;FThreadList: TList;FTaskObjectList: TList;FThreadMaxNum: Integer;FOnTerminatingTask: TOnTerminatingTask;FThreadPriority: TThreadPolicyInt;FNextTaskID: Cardinal;// 可记录已处理的任务数procedure SetThreadMaxNum(const Value: Integer);procedure SetOnTerminatingTask(const Value: TOnTerminatingTask);procedure SetThreadPriority(const Value: TThreadPolicyInt);protectedfunction GetIdelThreadNum(): Integer;function WakeUpThreads(iNum:Integer): Integer;procedure GetTaskFromList(var TaskObject: TTaskObject; bPop:Boolean=True);procedure AddTaskToList(TaskObject: TTaskObject);procedure DeleteTaskFromList(TaskObject: TTaskObject);procedure ClearTaskList();procedure ClearThreadList();procedure ClearList();publicconstructor Create();virtual;destructor Destroy();override;procedure AddTask(TaskObject: TTaskObject);procedure KillTask(TaskObject: TTaskObject);procedure Clear();procedure WaitFor(iTimeOut:Cardinal);virtual;function IsThreadDone():Boolean;property ThreadMaxNum: Integer read FThreadMaxNum write SetThreadMaxNum;property ThreadPriority: TThreadPolicyInt read FThreadPriority write SetThreadPriority;property OnTerminatingTask: TOnTerminatingTask read FOnTerminatingTask write SetOnTerminatingTask;end;
implementation
typeTTaskStatus = (tsRunning, {tsSuspend, tsWillTerminate, }tsTerminating, tsTerminated, tsDestroying);
TThreadItem = class(TThread)privateFCriticalSectionLocker: TCriticalSectionLocker;FOwner: TThreadPool;FTaskStatus: TTaskStatus;// FNextTaskStatus: TTaskStatus;FCurTaskObject: TTaskObject;procedure SetOwner(const Value: TThreadPool);protectedprocedure Execute();override;procedure SetTaskStatus(TaskStatus: TTaskStatus);publicconstructor Create();overload; virtual;destructor Destroy();override;property Owner: TThreadPool read FOwner write SetOwner;end;
{ TThreadPool }
constructor TThreadPool.Create;beginFCriticalSectionLocker:= TCriticalSectionLocker.Create;FThreadList:=TList.Create;FTaskObjectList:=TList.Create;FThreadMaxNum := 3;FThreadPriority := 4;end;
destructor TThreadPool.Destroy;beginClearList();FThreadList.Destroy;FThreadList := nil;FTaskObjectList.Destroy;FTaskObjectList := nil;FCriticalSectionLocker.Destroy;inherited;end;
procedure TThreadPool.KillTask(TaskObject: TTaskObject);beginDeleteTaskFromList(TaskObject);end;
procedure TThreadPool.SetThreadMaxNum(const Value: Integer);beginFThreadMaxNum := Value;end;
procedure TThreadPool.AddTask(TaskObject: TTaskObject);beginAddTaskToList(TaskObject);end;
procedure TThreadPool.AddTaskToList(TaskObject: TTaskObject);varThreadItem: TThreadItem;beginif not FCriticalSectionLocker.EnterLocker() then Exit;tryif FTaskObjectList.IndexOf(TaskObject)>=0 then Exit;FTaskObjectList.Add(TaskObject);TaskObject.FTaskID := FNextTaskID;Inc(FNextTaskID);//检查线程数是否足够//======================================if WakeUpThreads(1)=0 then//没有线程被唤醒if FThreadList.Count < FThreadMaxNum thenbeginThreadItem:= TThreadItem.Create();ThreadItem.Priority := TThreadPriority(FThreadPriority);FThreadList.Add(ThreadItem);ThreadItem.FOwner := Self;WakeUpThreads(1);end;finallyFCriticalSectionLocker.LeaveLocker();end;end;
procedure TThreadPool.GetTaskFromList(var TaskObject: TTaskObject; bPop:Boolean=True);beginTaskObject := nil;if not FCriticalSectionLocker.EnterLocker() then Exit;tryif FTaskObjectList.Count=0 then Exit;TaskObject := TTaskObject(FTaskObjectList.Items[0]);if bPop then FTaskObjectList.Delete(0);finallyFCriticalSectionLocker.LeaveLocker();end;end;
procedure TThreadPool.DeleteTaskFromList(TaskObject: TTaskObject);variIndex: Integer;beginif not FCriticalSectionLocker.EnterLocker() then Exit;tryif Assigned(TaskObject) then Exit;iIndex := FTaskObjectList.IndexOf(Pointer(TaskObject));if iIndex = -1 then Exit;if TaskObject.FOwner=nil then Exit;if TThreadItem(TaskObject.FOwner).FTaskStatus<>tsTerminated thenbeginTaskObject.Terminate();TaskObject.WaitFor(DWORD(-1));end;FTaskObjectList.Delete(iIndex);finallyFCriticalSectionLocker.LeaveLocker();end;end;
procedure TThreadPool.SetOnTerminatingTask(const Value: TOnTerminatingTask);beginFOnTerminatingTask := Value;end;
function TThreadPool.GetIdelThreadNum: Integer;varI: Integer;beginResult := 0;if FThreadList.Count>0 thenfor I:=0 to FThreadList.Count-1 dobeginif TThread(FThreadList.Items[I]).Suspended thenInc(Result);end;end;
function TThreadPool.WakeUpThreads(iNum: Integer): Integer;varI: Integer;beginResult := 0;if FThreadList.Count>0 thenfor I:=0 to FThreadList.Count-1 dobeginif TThread(FThreadList.Items[I]).Suspended thenTThread(FThreadList.Items[I]).Resume;end;end;
procedure TThreadPool.ClearList;beginClearTaskList();ClearThreadList();end;
procedure TThreadPool.ClearTaskList;varI: Integer;begin//if not FCriticalSectionLocker.EnterLocker() then Exit;//tryif FTaskObjectList.Count>0 thenfor I:=FTaskObjectList.Count-1 downto 0 dobeginif TTaskObject(FTaskObjectList.Items[I])<>nil thenif (TTaskObject(FTaskObjectList.Items[I]).FOwner<>nil) thenbeginTTaskObject(FTaskObjectList.Items[I]).Terminate();TTaskObject(FTaskObjectList.Items[I]).WaitFor(DWORD(-1));if (TTaskObject(FTaskObjectList.Items[I])<>nil) andAssigned(TTaskObject(FTaskObjectList.Items[I])) thenTTaskObject(FTaskObjectList.Items[I]).FOwner := nil;end;//不能释放。。因为不是TThreadPool创建的资源//TTaskObject(FTaskObjectList.Items[I]).Destroy;FTaskObjectList.Delete(I);end;//finally//FCriticalSectionLocker.LeaveLocker();//end;end;
procedure TThreadPool.ClearThreadList;varI: Integer;beginif FThreadList.Count>0 thenfor I:=FThreadList.Count-1 downto 0 dobeginif Assigned(TThreadItem(FThreadList.Items[I])) thenbeginif (TThreadItem(FThreadList.Items[I]).FCurTaskObject<>nil) thenbeginif (TThreadItem(FThreadList.Items[I]).FTaskStatus<>tsTerminated) thenbeginTThreadItem(FThreadList.Items[I]).FCurTaskObject.Terminate;TThreadItem(FThreadList.Items[I]).FCurTaskObject.WaitFor(DWORD(-1));if (TThreadItem(FThreadList.Items[I]).FCurTaskObject <>nil) andAssigned(TThreadItem(FThreadList.Items[I]).FCurTaskObject) thenTThreadItem(FThreadList.Items[I]).FCurTaskObject.FOwner := nil;end;end;TThreadItem(FThreadList.Items[I]).Free;end;FThreadList.Delete(I);end;end;
procedure TThreadPool.WaitFor(iTimeOut: Cardinal);variFirst: Cardinal;beginiFirst := GetTickCount();while (iTimeOut=DWORD(-1)) or((GetTickCount()-iFirst)>=iTimeOut) dobeginif IsThreadDone() then Break;Sleep(10);end;end;
function TThreadPool.IsThreadDone: Boolean;varI: Integer;beginResult := False;if not FCriticalSectionLocker.EnterLocker() then Exit;try//任务不为空时肯定没有完成,可立即返回Falseif (FTaskObjectList<>nil) and (FTaskObjectList.Count=0) thenbeginfor I:=0 to FThreadList.Count-1 doif not (TThreadItem(FThreadList.Items[I]).Suspended orTThreadItem(FThreadList.Items[I]).Terminated) then Exit;//Suspended then Exit;Result := True;end;finallyFCriticalSectionLocker.LeaveLocker();end;end;
procedure TThreadPool.SetThreadPriority(const Value: TThreadPolicyInt);beginFThreadPriority := Value;end;
procedure TThreadPool.Clear();beginClearList();FNextTaskID := 0;end;
{ TThreadItem }
constructor TThreadItem.Create();beginFCriticalSectionLocker:= TCriticalSectionLocker.Create;Create(True);FTaskStatus:= tsTerminated;end;
destructor TThreadItem.Destroy;beginFCriticalSectionLocker.Destroy;FTaskStatus:= tsDestroying;inherited;end;
procedure TThreadItem.Execute;varTaskObject: TTaskObject;begininherited;while not Self.Terminated dobegin//申请任务if FOwner=nil then Break;FOwner.GetTaskFromList(TaskObject);//无任务。挂起等待Pool唤醒if TaskObject=nil thenbeginSelf.Suspend;Continue;//保证唤醒后重新申请任务end; //绑定任务与当前线程TaskObject.FOwner := Self;TaskObject.FThreadID := Self.ThreadID;FCurTaskObject := TaskObject;Self.SetTaskStatus(tsRunning);//执行任务TaskObject.Execute();Self.SetTaskStatus(tsTerminating);Self.SetTaskStatus(tsTerminated);if Assigned(TaskObject.FOnTerminateTask) then TaskObject.FOnTerminateTask(TaskObject);//解除当前绑定关系FOwner.DeleteTaskFromList(TaskObject);TaskObject.FOwner := nil;FCurTaskObject := nil;if Assigned(FOwner.FOnTerminatingTask) then FOwner.FOnTerminatingTask(FOwner, TaskObject);end;//不释放线程时,挂起,保留线程资源if FTaskStatus<>tsDestroying thenSelf.Suspended := True;end;
procedure TThreadItem.SetOwner(const Value: TThreadPool);beginFOwner := Value;end;
procedure TThreadItem.SetTaskStatus(TaskStatus: TTaskStatus);beginif not Assigned(Self) or (not Assigned(FCriticalSectionLocker)) thenbeginif Self<>nil then ;Exit;end;if not FCriticalSectionLocker.EnterLocker() then Exit;tryFTaskStatus := TaskStatus;finallyFCriticalSectionLocker.LeaveLocker;end;end;
{ TTaskObject }
constructor TTaskObject.Create;begin//end;
destructor TTaskObject.Destroy;beginTerminate();WaitFor(DWORD(-1));inherited;end;
procedure TTaskObject.SetOnTerminateTask(const Value: TOnTerminateTask);beginFOnTerminateTask := Value;end;
procedure TTaskObject.Synchronize(AMethod: TThreadMethod);beginTThread.Synchronize(Self.FOwner, AMethod);end;
procedure TTaskObject.Terminate;beginif FOwner<>nil thenTThreadItem(FOwner).SetTaskStatus(tsTerminating);//if Assigned(FOnTerminatingTask) then FOnTerminatingTask(Self);//WaitFor();end;
procedure TTaskObject.WaitFor(iTimeOut: Cardinal);variFirst: Cardinal;beginiFirst := GetTickCount();if Self=nil then Exit;if FOwner=nil then Exit;trywhile (Self<>nil) and (FOwner<>nil) and Assigned(FOwner) and (TThreadItem(FOwner).FTaskStatus<>tsTerminated) dobeginif (GetTickCount()-iFirst)>=iTimeOut then Break;Sleep(5);end;exceptend;end;
end.
相关阅读 >>
Delphi richedit控件中插入图片bmp(bmp,文件),gif(文件)
Delphi mysql里Delphi事件类型转unix时间戳
更多相关阅读请进入《Delphi》频道 >>