应用程序关闭时内存泄漏(由于工作线程)

时间:2014-03-13 08:38:38

标签: multithreading delphi

关闭应用程序后获取泄漏报告(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(持有工作线程的参考)&gt;&gt;

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

TMaster的析构函数(我从这里设置工作线程的终止标志)&gt;&gt;

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

在主窗体的OnClose事件处理程序中释放TMaster实例&gt;&gt;

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的析构函数&gt;&gt;

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

Tsrch_slave_thread.DoTerminate&gt;&gt;

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

Tsrch_slave_thread的OnTerminate事件处理程序&gt;&gt;

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 个答案:

答案 0 :(得分: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会使代码难以阅读。