2015-11-27 109 views
-1

我試圖重寫虛的TThread :: Terminate方法,但我發現我的覆蓋終止標誌設置只之後被調用。什麼是實施這個的正確方法?實現覆蓋線程終止方法

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

System.Classes.TThread.Terminate方法,已被覆蓋,如果你想設置的 Terminate屬性之前要調用的方法。
Terminate方法:

信號線由Terminated屬性設置爲true終止。

System.Classes.TThread.DoTerminate文檔:

DoTerminate調用OnTerminate事件處理程序,但不會終止線程。

另一個有趣的過程,是OnTerminate事件之前調用但Terminate屬性設置爲TrueSystem.Classes.TThread.TerminatedSet被聲明爲 abstract TThreadvirtual


我這裏有沒有IDE,但現在我想,如果你在TThread類看,你會發現Terminate屬性設置爲TrueOnTerminate觸發事件處理程序。

+0

這看起來像答案。它看起來TThread.DoTerminate在TThread.Execute方法完成後調用,它的主要目的是調用TThread.OnTerminated事件。我懷疑這可能是一個共同的使用可以釋放資源? – AlainD

+0

請注意,TThread :: Terminate沒有聲明爲虛擬的,所以可以直接覆蓋它? TThread :: DoTerminate被聲明爲虛擬。 – AlainD

+0

@AlainD它應該像你說的,但也處理'Execute'方法中發生的異常,我記得。對不起,目前沒有IDE我無法檢查 – fantaghirocco

4

據我瞭解,有信息從這個問題缺少的。閱讀您以前的問題(Alternative to sleep inside a thread)和評論跟蹤非常重要。

正試圖安排,爲Terminate一個呼叫信號,你的線程正在等待一個事件。爲了發生這種情況,您需要將呼叫掛接到Terminate。因爲它們在線程程序完成之後執行,所以不好等待DoTerminateOnTerminate

在現代版本的Delphi您可以覆蓋TerminatedSet。這正是你需要的。它從Terminate內部發射。

在老版本的Delphi,即預售日期這種方法,沒有辦法從Terminate方法通知。據我瞭解,這是關鍵。您希望掛鉤Terminate,並且在添加TerminatedSet之前,不存在此類掛鉤。

如果TerminatedSet不適用於您,那麼您將需要在您的課堂上提供一個調用Terminate的方法,然後執行您必須執行的其他任何操作。例如:

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