问题
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 theOnTerminate
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