Multithreading with TThread
28.1 Subclassing TThread
type
TWorker = class(TThread)
private
FProgress: Integer;
procedure UpdateUI;
protected
procedure Execute; override;
public
constructor Create;
end;
constructor TWorker.Create;
begin
inherited Create(True); // create suspended
FreeOnTerminate := True; // frees itself when done (then don't keep or touch the reference!)
end;
procedure TWorker.Execute;
begin
NameThreadForDebugging('Worker');
for var I := 1 to 100 do
begin
if Terminated then Exit; // cooperative cancellation
Sleep(50); // simulate work
FProgress := I;
Synchronize(UpdateUI); // run on the main thread (blocking)
// or Queue(UpdateUI); // non-blocking
end;
end;
procedure TWorker.UpdateUI;
begin
MainForm.ProgressBar1.Position := FProgress;
end;
// Start
var W := TWorker.Create;
W.Start;28.2 Anonymous Threads
TThread.CreateAnonymousThread(
procedure
begin
var Data := LoadDataFromServer; // background work
TThread.Queue(nil,
procedure
begin
Memo1.Lines.Text := Data; // safely update the UI on the main thread
end);
end).Start;28.3 Thread Rules
Never touch VCL/FMX controls from a background thread. Use Synchronize/Queue (or TThread.ForceQueue).
Thread lifecycle: Create(Suspended), Start, Terminate (sets the flag), WaitFor, FreeOnTerminate, OnTerminate event (runs in the main thread), Priority, ThreadID, TThread.CurrentThread, TThread.Sleep, TThread.Yield.
Thread-local variables: threadvar Counter: Integer;.