线程终止(再次......)

kid*_*bro 1 delphi multithreading

当我通过将终止标志设置为true来停止线程'srch_slave_thread'时,(srch_slave_thread.terminate)释放线程在析构函数的'inherited'行停止,为什么?是挂起的WaitFor吗?如果我在析构函数中注释掉'inherited',那么线程就会停止并释放自己.

取出'继承'并调出代码后:为什么线程在调用析构函数后会跳转到DoTerminate方法?

谢谢.

Tsrch_slave_thread = class(TThread)   
private
  FSW: TStopWatch;
protected
  procedure Execute; override;
public
  SimpleEvent: TSimpleEvent;
  procedure DoTerminate; override;
  ...
  constructor Create; 
  destructor Destroy; override;
end;
Run Code Online (Sandbox Code Playgroud)

创建事件obj.在构造函数中>>

constructor Tsrch_slave_thread.create;
begin
  inherited create(true);   
  Fsw := TStopWatch.Create;
  SimpleEvent := TSimpleEvent.Create;
end;
Run Code Online (Sandbox Code Playgroud)

调用析构函数后跳转到这里?>>

procedure Tsrch_slave_thread.DoTerminate;
begin
  inherited;
  self.simpleEvent.SetEvent; 
end;
Run Code Online (Sandbox Code Playgroud)

线程在析构函数>>中继承

destructor Tsrch_slave_thread.destroy;
begin
  self.SimpleEvent.free;
  inherited;
end;
Run Code Online (Sandbox Code Playgroud)

在这里创建线程>>

function TMaster.th_slvsearch_start: integer; 
begin
  if not Assigned( Fslave_search_thread ) then begin
    Fslave_search_thread := TFslave_search_thread.create;
    ... 
  end
  else begin  
    ...
    exit;
  end;  
  with Fslave_search_thread do
  begin    
    master := self;  
    master_HWND := self.fMsgHandlerHWND;
    FreeOnTerminate := false;
    OnTerminate := slvsrch_termination;
    start;         
  end;
end;
Run Code Online (Sandbox Code Playgroud)

陷阱线程从这里开始>>

procedure TMaster.th_slvsearch_stop;
begin
  Fslave_search_thread.Terminate; 
end;
Run Code Online (Sandbox Code Playgroud)

线程.执行>>

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;
Run Code Online (Sandbox Code Playgroud)

OnTerminate事件处理程序>>

procedure TMaster.slvsrch_termination(Sender: TObject);
begin
  if Assigned( Fslave_search_thread ) then
  begin
    self.FLastSearchTime := Fslave_search_thread.FSW.ElapsedMilliseconds / 1000;
    Fslave_search_thread.Free; 
    Fslave_search_thread := nil;
    self.Factive_slv_search := 0;
  end;
  ...
end;
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 6

您正在Free从其OnTerminate事件处理程序调用线程对象.仅此一点是错误的,因为在触发事件时无法释放对象,因为当事件返回时,您现在正在执行已被破坏的对象中的代码.

但那不是你眼前的问题.由于调用WaitForin,你已经使线程陷入僵局TThread.Destroy.线程无法完成,因为它在等待自己.线程上的调用堆栈如下所示:

Synchronize(CallOnTerminate)
DoTerminate
ThreadProc

所以线程正在等待主线程完成执行CallOnTerminate.在主线程上,你的OnTerminate处理程序内部是调用Free.这反过来导致呼叫WaitFor.因此主线程正在等待线程完成.那是你经典的僵局.线程A在线程B上等待,线程B在线程A上等待.

故事的寓意:永远不要Free在其OnTerminate事件处理程序中调用一个线程.

解决方案可能是设置FreeOnTerminateTrueOnTerminate处理程序设置Fslave_search_threadnil.