什么可能导致一个C + + Builder / Delphi线程和应用程序不closures?

有一次,在testing过程中,我的C ++ Builder / Delphi应用程序在后台工作线程中引发了一个未捕获的exception。 EurekaLog抓住了这个例外,并发出了一个错误报告,正如我所料,一切似乎都没有问题。

但是,当我closures应用程序的主窗口时,仍然有一些东西在后台运行,因为应用程序仍然在任务pipe理器中列出(仍然有资源打开)。

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

什么可能导致一个线程和应用程序保持这样运行,甚至在主窗口closures之后(并且大概PostQuitMessage被调用)?

我怎样才能确保应用程序总是干净地closures?

第一个规则是线程主要执行程序方法应该被写入,以便它们可以被正确地发信号和关闭,第二个规则是不应该先关闭应用程序的主线程,然后希望其他线程关闭为了安全起见,你应该指示所有的后台线程停止,等待关闭完成,然后关闭你的主线程。 一个最小的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

如果你做了一个无限循环(虽然是真的),应用程序不会干净地关闭,即使它看起来像你。 不知何故,应用程序被终止,正在运行的线程可能会突然消失,或者它们可能会死锁或以其他方式失败,因为它们可能正在使用线程2中正在忙于线程1中的资源。

你可能有一个或多个有意的竞争条件,因为你可能没有写你的线程执行方法是可中断的,或者你可能会开始关闭主应用程序线程和VCL及其对象,然后再确定你的后台线程是完全关闭。

你确定工作线程终止,主线程没有等待它完成吗?