2014-03-13 41 views
1

關閉應用程序後獲取泄漏報告(Tsrch_slave_thread,TSimpleEvent)。我知道應用程序退出之前,線程可以釋放自己,但如何避免?如何等待線程完成?應用程序關閉時內存泄漏(由於工作線程)

謝謝。工作線程的


定義>>
- FreeOnTerminate設置爲true
- OnTerminate:TMaster.slvsrch_termination();

Tsrch_slave_thread = class(TThread) 
private 
    FSW: TStopWatch; 
protected 
    procedure Execute; override; 
public 
    SimpleEvent: TSimpleEvent; 
    master: TMaster; 
    master_HWND: HWND; 
    procedure DoTerminate; override; 
    constructor Create; 
    destructor Destroy; override; 
end; 

procedure Tsrch_slave_thread.Execute; 
var 
    text_orig: string; 
    activesearch: integer; 
begin 
    FSW.Start; 
    while not terminated do begin 
    activesearch := master.CMD_LISTCNT; 
    //stopper refresh 
    synchronize(procedure begin   
     with self.master do 
      Fmasternode.text := FmasterDat.MstrName + ' (' + floattostr(Fsw.ElapsedMilliseconds/1000) + 'sec - Searching)'; 
    end); 
    if (SimpleEvent.WaitFor(2000) <> wrTimeOut) or (activesearch <> 1) then break; 
    end; 
    FSW.Stop; 
end; 

TMaster(持有工作線程參考)>>

TMaster = class(TObject) 
private 
    ... 
    Fslave_search_thread : Tsrch_slave_thread; 
    ... 
public 
    ... 
end; 

TMaster的析構函數(我設定的工作線程的從這裏結束標誌)>>

destructor TMaster.Destroy; 
begin 
    FSlaveList.free; 
    DeallocateHWnd(fMsgHandlerHWND); 
    if assigned(self.Fslave_search_thread) then self.Fslave_search_thread.terminate; 
    inherited;  
end; 

在主窗體的OnClose事件中釋放TMaster實例dler >>

procedure TfrmCLmain.FormClose(Sender: TObject; var Action: TCloseAction); 
    ... 
    node := frmDevTree.JvTreeView1.Items.GetFirstNode; 
    if node.data <> nil then 
    begin 
    while Assigned(Node) do begin 
     if TObject(node.data) is TMaster then 
     TMaster(node.data).free; 
     node := node.getNextSibling; 
    end; 
    end; 
    ... 
    freeandnil(udpsend); 
    action := caFree; 
end; 

Tsrch_slave_thread的析構函數>>

destructor Tsrch_slave_thread.destroy; 
begin 
    self.SimpleEvent.free; 
    inherited; 
end; 

Tsrch_slave_thread.DoTerminate >>

procedure Tsrch_slave_thread.DoTerminate; 
begin 
    inherited; 
    self.master.FlastSearchTime := self.FSW.ElapsedMilliseconds/1000; 
    self.simpleEvent.SetEvent; 
end; 

Tsrch_slave_thread的OnTerminate事件處理>>

procedure TMaster.slvsrch_termination(Sender: TObject); 
begin 
    if Assigned(Fslave_search_thread) then 
    begin 
    self.FLastSearchTime := Fslave_search_thread.FSW.ElapsedMilliseconds - SEARCH_DELAY_SEC; 
    Fslave_search_thread := nil; 
    end; 
    ... 
    postmessage (self.FMasterDevFrmHND, WM_SLVSRCH_COMPLETE, integer(self), 0); 
end; 

回答

1

簡單地說,你需要銷燬線程並終止它。在終止線程後立即添加對Free的呼叫。

destructor TMaster.Destroy; 
begin 
    FSlaveList.free; 
    DeallocateHWnd(fMsgHandlerHWND); 
    if assigned(Fslave_search_thread) then 
    Fslave_search_thread.terminate; 
    Fslave_search_thread.Free; 
    inherited; 
end; 

另外,過量使用Self會使代碼難以閱讀。

+0

謝謝。如何確定應用程序是否已關閉?因爲在TMaster.slvsrch_termination中我有一個同時銷燬的表單的消息,所以我不必費心發送這條消息。 – grinner

+0

我真的不明白這個問題。你不能在'TMaster.Destroy'之後的線程中調用'Free',因爲在那之後你再也沒有對線程的引用了。顯然,TMaster實例正在被破壞,所以答案中的代碼有什麼問題? –

+0

是的,我明白了,那只是我碰到的另一個(間接)問題。但是,我應該爲此打開另一條線索。 – grinner