Az alábbi szál tipikusan olyan használatra alkalmas, amikor valamilyen műveletet kell végrehajtani a háttérben és ha az befejeződött, akkor felszabadítja a szálat.
A szál kódja az alábbi:
unit UTestThread; interface uses Classes; type TProgressChanged = procedure (Sender : TObject; AProgress : Integer) of object; TestThread = class(TThread) private { Private declarations } FProgress : Integer; FOnProgressChanged : TProgressChanged; protected procedure SyncDoOnProgressChanged; procedure DoOnProgressChanged; virtual; procedure Execute; override; public constructor Create(AOnProgressChangeCallBack : TProgressChanged; AOnTerminateCallBack : TNotifyEvent); destructor Destroy; override; property OnProgressChanged : TProgressChanged read FOnProgressChanged write FOnProgressChanged; end; implementation uses SysUtils; { TestThread } constructor TestThread.Create(AOnProgressChangeCallBack: TProgressChanged; AOnTerminateCallBack: TNotifyEvent); begin inherited Create(True); FreeOnTerminate := False; Priority := tpNormal; FOnProgressChanged := AOnProgressChangeCallBack; Self.OnTerminate := AOnTerminateCallBack; Resume; end; destructor TestThread.Destroy; begin inherited Destroy; end; procedure TestThread.DoOnProgressChanged; begin if Assigned(OnProgressChanged) then FOnProgressChanged(Self, FProgress); end; procedure TestThread.Execute; begin if Terminated then Exit; FProgress := 0; while (FProgress < 1000) and (not Terminated) do begin Inc(FProgress); SyncDoOnProgressChanged; Sleep(100); end; end; procedure TestThread.SyncDoOnProgressChanged; begin Synchronize(DoOnProgressChanged); end; end.A szál létrehozásakor a szál konstruktorában két callback függvényt kell megadni. Az egyik ami a folyamat állapotát aktualizálja, a másik pedig a szál befejeződésekor hívódik meg.
A szálat vezérlő modul kódja pedig így néz ki:
... const WM_FREE_THREAD = WM_USER + 1; type TfrmMainTest = class(TForm) btnStart: TButton; ed1: TEdit; btnStop: TButton; procedure btnStartClick(Sender: TObject); procedure btnLeakClick(Sender: TObject); procedure btnStopClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } FThread : TestThread; procedure OnThreadFinished(Sender : TObject); procedure OnProgressChanged(Sender : TObject; AProgress : Integer); procedure StopWorkerThread; public { Public declarations } procedure WndProc(var Message: TMessage); override; destructor Destroy; override; end; var frmMainTest: TfrmMainTest; implementation uses Math; {$R *.dfm} procedure TfrmMainTest.btnStartClick(Sender: TObject); begin btnStart.Enabled := False; if not Assigned(FThread) then begin FThread := TestThread.Create(OnProgressChanged, OnThreadFinished); end; end; procedure TfrmMainTest.OnProgressChanged(Sender: TObject; AProgress: Integer); begin ed1.Text := IntToStr(AProgress); end; procedure TfrmMainTest.OnThreadFinished(Sender: TObject); begin PostMessage(Handle, WM_FREE_THREAD, 0, 0); end; procedure TfrmMainTest.StopWorkerThread; begin if (FThread <> nil) then begin FThread.Terminate; FThread.WaitFor; FreeAndNil(FThread); btnStart.Enabled := True; end; end; procedure TfrmMainTest.WndProc(var Message: TMessage); begin if (Message.Msg = WM_FREE_THREAD) then StopWorkerThread else inherited WndProc(Message); end; procedure TfrmMainTest.btnStopClick(Sender: TObject); begin if Assigned(FThread) then begin FThread.Terminate; end; end; destructor TfrmMainTest.Destroy; begin inherited Destroy; end; procedure TfrmMainTest.FormClose(Sender: TObject; var Action: TCloseAction); begin StopWorkerThread; end; ...
Az elindított szál minden esetben felszabadul és a szál futása is megszakítható.