当我停止线程' srch_slave_thread'将终止标志设置为true,(srch_slave_thread.terminate)释放线程停止在继承的'在析构函数中,为什么?是挂起的WaitFor吗?如果我发表评论“继承”'在析构函数中,线程停止并释放自己。
取出后继承的'和debuging代码:为什么线程在调用析构函数后跳转到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;
创建事件obj。在构造函数>>
中constructor Tsrch_slave_thread.create;
begin
inherited create(true);
Fsw := TStopWatch.Create;
SimpleEvent := TSimpleEvent.Create;
end;
在调用析构函数后跳转到这里? >>
procedure Tsrch_slave_thread.DoTerminate;
begin
inherited;
self.simpleEvent.SetEvent;
end;
线程在析构函数>>
中继承destructor Tsrch_slave_thread.destroy;
begin
self.SimpleEvent.free;
inherited;
end;
在这里创建线程>>
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;
将线程从这里开始>>
procedure TMaster.th_slvsearch_stop;
begin
Fslave_search_thread.Terminate;
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;
OnTerminate事件处理程序&gt;&gt;
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;
答案 0 :(得分:6)
您正在通过其Free
事件处理程序调用线程对象上的OnTerminate
。仅此一点是错误的,因为在触发事件时无法释放对象,因为当事件返回时,您现在正在执行已被破坏的对象中的代码。
但那不是你眼前的问题。由于WaitFor
中对TThread.Destroy
的调用,您已经使线程陷入僵局。线程无法完成,因为它在等待自己。线程上的调用堆栈如下所示:
Synchronize(CallOnTerminate) DoTerminate ThreadProc
因此线程正在主线程上等待完成执行CallOnTerminate
。在主线程上,OnTerminate
处理程序内部是对Free
的调用。这反过来会调用WaitFor
。因此主线程正在等待线程完成。那是你经典的僵局。线程A在线程B上等待,线程B在线程A上等待。
故事的寓意:永远不要在Free
事件处理程序内的线程上调用OnTerminate
。
解决方案可能是将FreeOnTerminate
设置为True
并将OnTerminate
处理程序集Fslave_search_thread
设置为nil
。