2012-12-25 113 views
4

我有一個名爲TMyThread線程和我推翻這樣的執行過程:如何在完成運行之前停止線程?

procedure TMyThread.Execute; 
Begin 
    repeat 
    //Some Work 
    Sleep(5000); 
    //Some Work 2; 
    Sleep(5000); 
    until FActive=False 
End; 

在主窗體我有按鈕被稱爲「破壞我的主題」。我想銷燬我的線程,但問題是我的線程只有在完成其工作時纔會被銷燬。即使尚未完成工作,我也想摧毀我的線程。我該怎麼做呢?

+0

檢查了這一點: http://stackoverflow.com/questions/4044855/how-to-kill-a-thread-in-delphi – kostas

+4

從技術上講這是可能的,但它是一個真的* *糟糕的主意。不要殺死線程,告訴他們自殺。正確的解決方案是讓線程經常檢查一個標誌(例如'Terminated'屬性)。 – CodesInChaos

+4

如果您希望您的工作線程進入睡眠狀態,請勿使用睡眠,因爲在此期間線程沒有偵聽(終止)。使用Events和WaitForSingleObject作爲例如在這裏指定:http://objectmix.com/delphi/402360-tthread-sleep-terminate.html(當谷歌搜索「delphi終止線程setevent」時發現) –

回答

2

使用TEvent可以解決這個問題 這是一個如:如果我想殺死我的線程

uses SyncObjs; 
    TMyThread = class(TThread) 
     private 
     FTerminateEvent: TEvent; 
     protected 
     procedure Execute; override ; 
     public 
     constructor Create(ACreateSuspended: Boolean); overload; 
     destructor Destroy; override; 
     procedure Stop; 
     end; 
    constructor TMyThread.Create(ACreateSuspended: Boolean); 
    begin 
    FTerminateEvent := TEvent.Create(nil, True, False, 'FTerminateEvent'); 
    inherited Create(ACreateSuspended); 
    end; 

    destructor TMyThread.Destroy; 
    begin 
    FTerminateEvent.Free; 
    inherited; 
    end; 

    procedure TMyThread.Stop; 
    begin 
    Terminate; 
    FTerminateEvent.SetEvent; 
    end; 

    procedure TMyThread.Execute; 
    begin 
     while not Terminated do 
     begin 
     // do somthing interesting! 
     FTerminateEvent.WaitFor(5000); 
     end; 
    end; 

現在,所有我需要做的就是調用MyThread.Stop比調用MyThread.Free。

+3

爲什麼選擇實現自己的並行機制而不是使用Terminate –

+2

要清楚如何執行此操作,您需要重寫'TThread.TerminatedSet'並在那裏調用'FTerminateEvent.SetEvent'。在你調用'inherited Destroy'之後,確保你釋放了'FTerminateEvent'。看到我更新的答案。 –

22

您的線程的Execute方法必須定期檢查線程的Terminated屬性的狀態。如果是True,則線程Execute方法必須退出。

所以,一個典型的Execute方法可能是這樣的:

procedure TMyThread.Execute; 
begin 
    while not Terminated do 
    DoNextPieceOfWork 
end; 

它看起來像你的線程都有自己的FActive標誌正在執行相同的任務。這個問題是TThread不知道它。所以你應該擺脫FActive,而是使用內置的機制。

當你在線程上調用Free時,它會調用Terminate。設置TerminatedTrue。然後它等待線程方法退出。這將發生,因爲你的線程通知TerminatedTrue並退出。然後線程的析構函數可以繼續並完成整理線程的工作。


看在你的答案代碼,倒不如寫利用現有Terminate機制。

type 
    TMyThread = class(TThread) 
    private 
    FTerminateEvent: TEvent; 
    protected 
    procedure Execute; override; 
    procedure TerminatedSet; override; 
    public 
    constructor Create(ACreateSuspended: Boolean); 
    destructor Destroy; override; 
    end; 

constructor TMyThread.Create(ACreateSuspended: Boolean); 
begin 
    inherited Create(ACreateSuspended); 
    FTerminateEvent := TEvent.Create(nil, True, False, ''); 
end; 

destructor TMyThread.Destroy; 
begin 
    inherited; 
    FTerminateEvent.Free; 
end; 

procedure TMyThread.TerminatedSet; 
begin 
    FTerminateEvent.SetEvent; 
end; 

procedure TMyThread.Execute; 
begin 
    while not Terminated do 
    begin 
    // do somthing interesting! 
    FTerminateEvent.WaitFor(5000); 
    end; 
end; 

現在不需要單獨的Stop方法。您可以在線索上撥打Free。然後調用Terminate。然後調用TerminatedSet。然後事件發出信號。然後Execute終止。然後線可以消失。


話雖如此,我很難想象一個5000毫秒超時會是最好的方法。我不知道你爲什麼這樣做,但我猜你正試圖調節線程,使其不能運行hot。你想避免繁忙的循環。這是令人欽佩的,但是使用固定超時並不是實現這一目標的方法。要做到這一點的方法是等待一個同步事件,通常是一個事件。然後當有更多的工作要做,事件就會變成信號,你的線程就會醒來。

+0

我使用FActive而不是終止 –

+0

大衛,我不wana我的線程等待線程方法(工作)退出.. –

+2

工作代碼還需要檢查終止。 –

1

你真的正在接近這個問題完全錯誤。將你的線程編碼爲只做你想讓他們做的工作,然後就不需要「從外部伸手」來控制它們。你覺得有必要從外部控制這個線程,因爲它正在做一些你不想做的事情 - 那麼爲什麼你首先編寫它來做到這一點?

+0

因爲我需要使用睡眠方法作爲等待在我做工作之前的時間 –

+2

您需要可中斷睡眠 –

+2

@ user1720557:這很好,然後睡覺。但是當你醒來時,明智地決定下一步該做什麼。 –

相關問題