我們經(jīng)常遇到在Form下操作界面,例如由線程控制的進(jìn)度條等,,讓線程的執(zhí)行可以和Form界面融合,,不必傳進(jìn)窗體句柄,,這個(gè)時(shí)候可以用回調(diào)函數(shù)的方法來定義線程的成員函數(shù)。
注意:原則上Delphi的多線程環(huán)境下,,對(duì)界面的輸出不能在其它線程中隨意進(jìn)行,,否則會(huì)導(dǎo)致與界面(主)線程本身的刷新操作形成沖突,導(dǎo)致一些看似無規(guī)律的問題。比較保險(xiǎn)的方式就是將要刷新的內(nèi)容通過消息或其它通信機(jī)制傳給界面線程,,由界面線程去完成實(shí)際的刷新操作,。
所以,在我們使用回調(diào)函數(shù)把線程的可執(zhí)行代碼轉(zhuǎn)移到Tform或其他類下時(shí),,只要不是直接操作VCL控件,,一般可以參考下面代碼,可以安全執(zhí)行,。下面的代碼就是一個(gè)可以自動(dòng)執(zhí)行線程成員事件OnExecute指向的代碼片段,,你只需要給線程實(shí)例對(duì)象的OnExecute
賦值即可讓其執(zhí)行。
用法說明:在Form下定義一個(gè)成員函數(shù)
TForm1= class(TForm)
........
public
procedure MyExecuteJob( AThreadSelf:TThread;var
State : TJobState);
end;
//實(shí)現(xiàn)部分
procedure TForm1.MyExecuteJob( AThreadSelf:TThread;var State :
TJobState);
在線程創(chuàng)建的時(shí)候,;即可賦值,,例如:
var
AutoChooseThread : TAutoChooseThread ;
procedure Tfrm_AutoChoose.StartChooseJob; begin if not
Assigned(AutoChooseThread) then begin AutoChooseThread :=
TAutoChooseThread.Create(True); AutoChooseThread.OnJObComplete :=
OnJObComplete; AutoChooseThread.OnBeforeJobRun :=
OnBeforeJobRun; AutoChooseThread.OnProgress := OnProgress;
AutoChooseThread.OnExecute := MyExecuteJob; end;
end;
以上使用說明,需要完成其他回調(diào)只要按照如上方式即可,。需要注意到地方,。例如:MyExecuteJob函數(shù)
在Form1中定義了,那么傳入了兩個(gè)參數(shù),,一個(gè)是線程本身,,一個(gè)是線程狀態(tài)。如果MyExecuteJob函數(shù)中有大量循環(huán)操作,,不能立即返回,,需要不斷判斷線程狀態(tài),如果發(fā)現(xiàn)是JsStop或JsDestroy那么就需要Exit一下,,退出函數(shù),。否則調(diào)用FreeJob();或StopJob();是不能立即奏效的。
//線程回調(diào)函數(shù)類型定義 TJobState =
(JsStop,JsRunning,JsComplete,JsCreate,JsDestroy); //枚舉任務(wù)狀態(tài) TOnJObComplete =
procedure (Sender : TObject) of Object; //當(dāng)完畢 TOnJObRun =
procedure(Sender:TObject) of object; //開始 TOnProgress = procedure(
MaxValue,CurValue:DWORD) of object; //進(jìn)度 TOnExecute = procedure(
AThreadSelf:TThread;var State : TJobState) of object; //任務(wù)執(zhí)行
//自動(dòng)選擇任務(wù),,線程處理定義,,和GUI可以高度融合的方式 TAutoChooseThread =
class(TThread) private FOnJObComplete :
TOnJObComplete; FOnJObRun : TOnJObRun; FOnProgress :
TOnProgress; FOnExecute : TOnExecute; FState :
TJobState; public property OnJObComplete : TOnJObComplete
read FOnJObComplete write FOnJObComplete; property OnBeforeJobRun :
TOnJObRun read FOnJObRun write FOnJObRun; property OnProgress :
TOnProgress read FOnProgress write FOnProgress; property OnExecute :
TOnExecute read FOnExecute write FOnExecute; property State :
TJobState read FState; procedure StartJob(); procedure
StopJob(); procedure FreeJob(); procedure
Execute();override; constructor
Create(isCreateSuspend:Boolean); destructor Destroy; override;
end; //線程實(shí)現(xiàn)代碼 constructor
TAutoChooseThread.Create(isCreateSuspend:Boolean); begin FreeOnTerminate
:= True; FState := JsCreate; inherited
Create(isCreateSuspend); end;
destructor TAutoChooseThread.Destroy; begin
inherited; end;
procedure TAutoChooseThread.Execute; begin while not Terminated
do begin //當(dāng)任務(wù)執(zhí)行前 if Assigned( FOnJobRun ) then
begin FOnJObRun(Self); end;
//執(zhí)行任務(wù) if Assigned( FOnExecute ) then begin
//執(zhí)行任務(wù) FState := JsRunning;
FOnExecute(self,FState); //如果任務(wù)成功完成 if FState = JsComplete
then begin if Assigned(FOnJObComplete)
then begin FOnJObComplete(Self);
end; end;
//如果任務(wù)銷毀 if FState = JsDestroy then
begin Exit; end; end; Suspend;
Sleep(1); end; end;
procedure TAutoChooseThread.FreeJob; begin Terminate; FState :=
JsDestroy; Resume(); end;
procedure TAutoChooseThread.StartJob; begin Resume(); FState :=
JsRunning; end;
procedure TAutoChooseThread.StopJob; begin FState :=
JsStop; end;
procedure Tfrm_AutoChoose.OnBeforeJobRun(Sender: TObject); begin
sGroupBox_Pocessing.Visible := True; sGauge1.Progress := 0;
qry_FactorOfFlower.Close; end;
procedure Tfrm_AutoChoose.OnExecute(AThreadSelf: TThread; var State:
TJobState); var MaxValue,CurValue:DWORD; begin //執(zhí)行任務(wù)
MaxValue := 1000; sGauge1.MaxValue := MaxValue; for CurValue := 0 to
MaxValue - 1 do begin if TAutoChooseThread(AThreadSelf).State =
JsStop then begin sGroupBox_Pocessing.Visible :=
False; sPanel_Result.Visible := False;
qry_FactorOfFlower.Close; Exit; end;
sGauge1.Progress := CurValue; end; State := JsComplete; end;
procedure Tfrm_AutoChoose.OnJObComplete(Sender: TObject); begin
sPanel_Result.Visible := True; end;
procedure Tfrm_AutoChoose.OnProgress(MaxValue, CurValue: DWORD); begin
end;
procedure Tfrm_AutoChoose.FormDestroy(Sender: TObject); begin
inherited; if Assigned( AutoChooseThread ) then begin
AutoChooseThread.FreeJob(); end; end;
|