我正在尝试覆盖虚拟的TThread :: Terminate方法,但是在设置Terminated标志后,我发现我的覆盖仅被调用。实现这个的正确方法是什么?
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;
答案 0 :(得分:5)
据我了解,问题中缺少信息。阅读上一个问题(Alternative to sleep inside a thread)和评论记录非常重要。
您正在尝试安排调用Terminate
来表示您的线程正在等待的事件。为了实现这一点,您需要将调用挂钩到Terminate
。等待DoTerminate
或OnTerminate
并不好,因为它们在线程程序完成后执行。
在现代版本的Delphi中,您可以覆盖TerminatedSet
。这正是你所需要的。它是从Terminate
内部触发的。
在旧版本的Delphi中,在此方法之前,无法通过Terminate
方法通知。据我了解,这是关键点。您希望挂钩Terminate
,并且在添加TerminatedSet
之前,不存在此类挂钩。
如果您无法使用TerminatedSet
,那么您需要在类上提供一个调用Terminate
的方法,然后执行您必须执行的任何其他操作。例如:
procedure TMyThread.SignalAndTerminate;
begin
FTerminationEvent.SetEvent;
Terminate;
end;
答案 1 :(得分:1)
如果要在设置 Terminate
属性之前调用方法,则必须覆盖System.Classes.TThread.Terminate方法。
Terminate
方法:
通过将
Terminated
属性设置为true来表示线程终止。
来自System.Classes.TThread.DoTerminate文档:
DoTerminate
调用OnTerminate
事件处理程序,但不终止该线程。
在OnTerminate
事件之前但在Terminate
属性设置为True
之后调用的另一个感兴趣的过程是System.Classes.TThread.TerminatedSet,它被声明为 {{ {}}}中的1}} abstract
。
我现在没有IDE,但我想如果你查看virtual
类,你会发现TThread
事件处理程序是在TThread
属性之后触发的设置为OnTerminate
。