Indy10线程池BUG:Idyarn线程使用Synchronize导致TerminateAllYarns挂死的解决办法

来源:互联网 发布:mac口红dareyou试色 编辑:程序博客网 时间:2024/06/11 21:53

写了个线程池程序。用TerminateAllYarns来结束线程,每次老是界面挂死在此段代码。
起初以为是代码同步或互斥问题,查了半天没找到。于是跟踪原代码进去,发现原来是这段代码导致了死循环 :

------------------IdScheduler.pas--------------

procedure TIdScheduler.TerminateAllYarns;
var
  i: Integer;
begin
  while True do begin
    // Must unlock each time to allow yarns that are temrinating to remove themselves from the list
    with FActiveYarns.LockList do try
      if Count = 0 then begin
        Break;
      end;
      for i := 0 to Count - 1 do begin
        TerminateYarn(TIdYarn(Items[i]));
      end;
    finally FActiveYarns.UnlockList; end;
    //TODO: Put terminate timeout check back
    Sleep(500); // Wait a bit before looping to prevent thrashing
  end;
end;

一旦idyarn调用对应线程使用了Synchronize,则必须有一段程序插到主线程去运行才能继续。结果主线程执行到此TerminateAllYarns时,就开始没完没了的置stop标志了。于是主线程就挂死在此了。

改进办法是:
在for i := 0 to Count - 1 do begin前加入Application.ProcessMessages;令主线程喘口气运行子线程的Synchronize代码,这样就不会在此没完没了的stop死循环了。

不过这样又得注意一个问题,就是一旦Application.ProcessMessages允许事件冒泡,那么可能重复触发TerminateAllYarns导致在FActiveYarns.LockList时死锁,因此设置判断避免TerminateAllYarns重复触发

 

原创粉丝点击