Implement override for thread Terminate method

回眸只為那壹抹淺笑 提交于 2020-02-08 10:02:47

问题


I am trying to override the virtual TThread::Terminate method, but am finding my override gets called only after the Terminated flag is set. What is the correct way to implement this?

TTestThrd = class(TThread)
private
    { Private declarations }

protected
    { Protected declarations }
    procedure Execute(); override;
    procedure DoTerminate(); override;

public
    { Public declarations }
end;


procedure TTestThrd.Execute();
var
    bTerminated: Boolean;
begin
    // This is the main thread loop
    try
        while (not Terminated) do
            begin
            // Sleep or use TEvent::Waitfor...
            end;
    finally
        // Terminated (or exception) so free all resources...
        bTerminated := True;        // Why is this called...
    end;
end;

procedure TTestThrd.DoTerminate();
var
    bDoTerminateCalled: Boolean;
begin
    bDoTerminateCalled := True;     // ...before this?  
    inherited;
end;

回答1:


The System.Classes.TThread.Terminate method has to be overridden if you want a method to be called before the Terminate property is set.
The Terminate method:

Signals the thread to terminate by setting the Terminated property to true.

From the System.Classes.TThread.DoTerminate documentation:

DoTerminate calls the OnTerminate event handler, but does not terminate the thread.

Another procedure of interest that is called before the OnTerminate event but after the Terminate property is set to True is System.Classes.TThread.TerminatedSet which is declared as abstract virtual in the TThread class.


I have no IDE with me right now but I guess that if you look in the TThread class, you'll find that the OnTerminate event handler is triggered after the Terminate property is set to True.




回答2:


As I understand it, there is information missing from the question. It is important to read your previous question (Alternative to sleep inside a thread) and the comment trail.

You are trying to arrange that a call to Terminate signals an event that your thread is waiting on. In order for that to happen, you need to hook the call to Terminate. It's no good waiting for DoTerminate or OnTerminate because they execute after the thread procedure has finished.

In modern versions of Delphi you can override TerminatedSet. That's exactly what you need. It is fired from inside Terminate.

In older versions of Delphi, that pre-date this method, there is no way to be notified from the Terminate method. As I understand it, that is the key point. You wish to hook Terminate, and before TerminatedSet was added, no such hook existed.

If TerminatedSet is not available to you, then you will need to provide a method on your class that calls Terminate, and then performs whatever other actions you must perform. For example:

procedure TMyThread.SignalAndTerminate;
begin
  FTerminationEvent.SetEvent;
  Terminate;
end;


来源:https://stackoverflow.com/questions/33962710/implement-override-for-thread-terminate-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!