有一次,在测试期间,我的C ++ Builder / Delphi应用程序在后台工作线程中引发了一个未捕获的异常。 EurekaLog抓住了异常并发送了错误报告,正如我预期的那样,一切似乎都没问题。
但是,当我关闭应用程序的主窗口时,后台仍在运行某些东西,因为应用程序仍然列在任务管理器中(并且仍然打开了资源)。
我试图通过故意在后台工作线程中引入各种错误来复制这个问题,但我不能。
什么可能导致线程和应用程序保持这样的运行,即使在主窗口关闭后(并且,可能是已调用PostQuitMessage)?
如何确保应用程序始终完全关闭?
答案 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时,如果AllBackgroundThreadsTerminated返回false,则将CanClose设置为false,然后设置FPendingShutdownFlag := true
。
如果你进行无限循环(同时为true),应用程序不会干净地关闭,即使它看起来像你。不知何故,应用程序被终止,并且正在运行的线程可能会突然消失,或者它们可能会死锁或以其他方式失败,因为它们可能正在使用线程2中的资源,而您正忙于在线程1中释放。
您可能有一个或多个故意竞争条件,因为您可能没有将您的线程执行方法编写为可中断的,或者您可以在确定您的主要应用程序线程和VCL及其对象之前关闭它们。后台线程完全关闭。
答案 1 :(得分:1)
您确定工作线程已终止,并且主线程没有等待它完成吗?