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ó.







