什么可能导致C ++ Builder / Delphi线程和应用程序无法关闭?

时间:2011-06-13 13:59:04

标签: windows multithreading delphi c++builder shutdown

有一次,在测试期间,我的C ++ Builder / Delphi应用程序在后台工作线程中引发了一个未捕获的异常。 EurekaLog抓住了异常并发送了错误报告,正如我预期的那样,一切似乎都没问题。

但是,当我关闭应用程序的主窗口时,后台仍在运行某些东西,因为应用程序仍然列在任务管理器中(并且仍然打开了资源)。

我试图通过故意在后台工作线程中引入各种错误来复制这个问题,但我不能。

什么可能导致线程和应用程序保持这样的运行,即使在主窗口关闭后(并且,可能是已调用PostQuitMessage)?

如何确保应用程序始终完全关闭?

2 个答案:

答案 0 :(得分:7)

第一个规则是应该编写线程主执行程序方法,以便可以正确地发出信号并关闭它们,第二个规则是你不应该首先关闭应用程序的主线程,然后希望其他线程在他们自己的时间关闭,为了安全起见,你应该发出所有后台线程停止信号,等待关闭完成,然后关闭你的主线程。最小的THREAD示例:

procedure TMyThread.Execute;
begin
   Init;
   while not Terminated do
      OneWorkItem; // inside OneWorkItem, you  ALSO need to check for Terminated
end;

最小主窗体/主线程示例:

   procedure TMyMainForm.CheckAndShutdown;
   begin
     if FPendingShutdownFlag then 
       if AllBackgroundThreadsTerminated then 
             Self.Close;
   end;

您可以设置FPendingShutdownFlag并从应用程序空闲处理循环调用上面的函数。当用户单击主窗体FormClose时,如果AllBackgroundThreadsT​​erminated返回false,则将CanClose设置为false,然后设置FPendingShutdownFlag := true

如果你进行无限循环(同时为true),应用程序不会干净地关闭,即使它看起来像你。不知何故,应用程序被终止,并且正在运行的线程可能会突然消失,或者它们可能会死锁或以其他方式失败,因为它们可能正在使用线程2中的资源,而您正忙于在线程1中释放。

您可能有一个或多个故意竞争条件,因为您可能没有将您的线程执行方法编写为可中断的,或者您可以在确定您的主要应用程序线程和VCL及其对象之前关闭它们。后台线程完全关闭。

答案 1 :(得分:1)

您确定工作线程已终止,并且主线程没有等待它完成吗?