You can use the TThread.OnTerminate event to determine when a thread has completed, for example:
procedure TForm1.Button1Click(Sender: TObject); begin if not Assigned(SupervisorThread) then begin SupervisorThread:= TSupervisorThread.Create(True); SupervisorThread.FreeOnTerminate := False; SupervisorThread.Priority := tpNormal; SupervisorThread.OnTerminate := SupervisorThreadTerminated; SupervisorThread.Resume; end; end; procedure TForm1.SupervisorThreadTerminated(Sender: TObject); begin SupervisorThread := nil; end;
However, this creates some problems. This creates a race condition since the cleaning thread acts on the SupervisorThread pointer, which can disappear at any time while the cleaning thread is still running. And this creates a memory leak, because you still need to free the SupervisorThread object after it finishes, but you cannot do it directly in the OnTerminate handler.
A better solution would not rely on a SupervisorThread pointer at all.
var SupervisorTerminated: TEvent; procedure TForm1.FormCreate(Sender: TObject); begin SupervisorTerminated := TEvent.Create(nil, True, True, ''); end; procedure TForm1.FormDestroy(Sender: TObject); begin if Assigned(SupervisorThread) then begin SupervisorThread.Terminate; while SupervisorTerminated.WaitFor(1000) = wrTimeout do CheckSynchronize; end; SupervisorTerminated.Free; end; procedure TForm1.Button1Click(Sender: TObject); begin if not Assigned(SupervisorThread) then begin SupervisorThread := TSupervisorThread.Create(True); SupervisorThread.FreeOnTerminate := True; SupervisorThread.Priority := tpNormal; SupervisorThread.OnTerminate := SupervisorThreadTerminated; SupervisorTerminated.ResetEvent; SupervisorThread.Resume; end; end; procedure TForm1.SupervisorThreadTerminated(Sender: TObject); begin SupervisorThread := nil; SupervisorTerminated.SetEvent; end;
procedure TCleaningThread.Execute; begin SupervisorTerminated.WaitFor(INFINITE); end;
procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin CanClose := (SupervisorTerminated.WaitFor(0) = wrSignaled); if not CanClose then ShowMessage('Cannot close form because Supervisor Thread is still working'); end;
source share