2011-06-13 108 views
2

一次,在测试过程中,我的C++ Builder/Delphi应用程序在后台工作线程中引发了未捕获的异常。如我所料,EurekaLog发现了异常并发送了错误报告,并且一切似乎都正常。但是,当我关闭应用程序的主窗口时,由于应用程序仍然在任务管理器中列出(并且仍然有资源打开),所以仍在后台运行一些内容。什么可能导致C++ Builder/Delphi线程和应用程序无法关闭?

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

什么会导致线程和应用程序继续像这样运行,即使主窗口已关闭(并且大概已调用PostQuitMessage)?

我该如何确保应用程序始终干净地关闭?

+0

你有没有可以无限阻止的EnterCriticalSection代码?这是一个非常常见的死机,在关机时就能正常工作。 – 2011-06-13 18:19:36

回答

7

第一条规则是线程主要执行程序方法应该被写入,以便它们可以正常发送并关闭,第二条规则是不应该只关闭应用程序的主线程,然后希望其他线程在自己的时间内关闭,为了安全起见,您应该指示所有后台线程停止,等待关闭完成,然后关闭主线程。一个最小的螺纹例如:

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及其对象完全关闭。

+0

我一定不能很好地解释自己。我尽我所能写我的线程是可以中断的,检查TThread.Terminated,以避免死锁和资源问题等。不知怎的,一次,尽管如此,我的应用程序没有终止;它仍然在后台运行,即使它的形式已经关闭。我想知道为什么以及如何预防它。我尽我所能想到的复制错误状态(包括添加无尽的while(true)循环),以便我找出如何从中恢复,但我仍然无法复制错误状态。 – 2011-06-13 15:27:38

+0

然后,它听起来像你正在寻找一个难以捉摸的竞争条件或其他类似的间歇性异步失败在你的代码。您是否有任何可能长时间阻止的TThread.Synchronize调用?你有睡眠()电话吗?例如,你可能会有我称之为“睡美人”的问题。后台线程在关闭主线程之前必须完全关闭,后台线程完全使用ANY对象或者主线程将释放。 – 2011-06-13 15:39:44

+0

在我看来,你应该先用大量的outputdebugstring消息来测试代码,然后在代码失败的客户端系统上运行它,以及MS DebugView(一个outputdebugstring查看器)并查看代码的哪些部分在客户端系统上达到或未达到。 – 2011-06-13 18:18:37

1

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

+0

我不确定发生了什么,我只看到过这个问题,但我想确保它不会在客户机器上重现。如果我故意让工作线程永不终止(通过在C++中添加一个“while(true);”循环),应用程序仍然完全关闭,所以我认为问题不在于主线程正在等待工人终止。 – 2011-06-13 14:10:52

+0

等一下。您添加了一个确保线程永不终止的while循环。但在其他地方可以打电话给TThread.Terminate。所以你所做的是使它不太可能会关闭干净。难怪你的应用程序坏了。 – 2011-06-13 15:10:51

+0

@Warren P:我想你可能误解了。看到我对你的答案的评论。 – 2011-06-13 15:28:58

相关问题