Search code examples
multithreadingdelphitthread

TThread.OnTerminate executing thread


The Delphi help for TThread.OnTerminate states that:

The method assigned to the OnTerminate event is executed in the context of the main thread rather than the context of the thread being terminated.

Is this even the case when the thread is created in another thread than the main thread?

So, is the OnTerminate called in the thread that created the TThread, or is it called in main thread? The IDE does not tells me this. When I debug, I see no active thread in the OnTerminate event. :-/


Solution

  • The documentation is correct. The OnTerminate event handler is always run in the main thread by default. Internally, TThread.DoTerminate() (which is called after the thread's Execute() method exits) uses TThread.Synchronize() to call the handler:

    function ThreadProc(Thread: TThread): Integer;
    var
      ...
    begin
      ...
      try
        if not Thread.Terminated then
        try
          Thread.Execute;
        except
          ...
        end;
      finally
        ...
        Thread.DoTerminate;
        ...
      end;
    end;
    
    procedure TThread.DoTerminate;
    begin
      if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
    end;
    
    procedure TThread.CallOnTerminate;
    begin
      if Assigned(FOnTerminate) then FOnTerminate(Self);
    end;
    

    If you want the OnTerminate handler to run in the context of the terminating thread (or any other thread you want), you can simply override DoTerminate() to call the handler however you want, eg:

    type
      TMyThread = class(TThread)
        ...
      protected
        ...
        procedure Execute; override;
        procedure DoTerminate; override;
        ...
      end;
    
    procedure TMyThread.Execute;
    begin
      ...
    end;
    
    procedure TMyThread.DoTerminate;
    begin
      // do whatever you want here, but DON'T call inherited!
      if Assigned(OnTerminate) then OnTerminate(Self);
    end;