【问题标题】:Implement override for thread Terminate method实现线程终止方法的覆盖
【发布时间】:2015-11-27 17:59:32
【问题描述】:

我正在尝试覆盖虚拟 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;

【问题讨论】:

    标签: multithreading delphi


    【解决方案1】:

    据我了解,问题中缺少信息。请务必阅读您之前的问题 (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;
    

    【讨论】:

      【解决方案2】:

      如果您希望在设置 Terminate 属性之前调用方法,则必须重写 System.Classes.TThread.Terminate 方法。
      Terminate 方法:

      通过将Terminated 属性设置为true 来指示线程终止。

      来自System.Classes.TThread.DoTerminate 文档:

      DoTerminate 调用OnTerminate 事件处理程序,但不终止线程。

      在OnTerminate 事件之前但在Terminate 属性设置为True 之后调用的另一个感兴趣的过程是System.Classes.TThread.TerminatedSet,它被声明为abstract virtual在TThread 类中。


      我现在没有 IDE,但我想如果你查看 TThread 类,你会发现在 Terminate 属性设置为 True 之后触发了 OnTerminate 事件处理程序.

      【讨论】:

      • 这看起来像是答案。似乎 TThread.DoTerminate 在 TThread.Execute 方法完成后被调用,它的主要目的是调用 TThread.OnTerminated 事件。我怀疑它的一个常见用途可能是释放资源?
      • 注意,TThread::Terminate 没有声明为虚拟的,所以可以直接覆盖它吗? TThread::DoTerminate 被声明为虚拟。
      • @AlainD 应该像你说的那样,而且我还记得处理Execute 方法中发生的异常。抱歉,目前没有 IDE,我无法检查
      • TerminatedSet 不是抽象的。终止不能被覆盖。
      • 哎呀......因为这显然是一堆废话,它不应该是公认的答案。请考虑删除接受的标志,我将删除答案本身。我认为没有理由编辑我的答案,因为另一个已经说明了我没有表达的意思。同时我要去write it out a hundred times "TerminatedSet 不是抽象的。Terminate 不能被覆盖。" 谢谢! :D
      猜你喜欢
      • 1970-01-01
      • 2017-09-27
      • 2012-09-16
      • 1970-01-01
      • 2019-07-01
      • 1970-01-01
      • 2015-11-19
      • 2019-01-14
      • 1970-01-01
      相关资源
      最近更新 更多