2

我们有一个 WinForms 桌面应用程序,它是多线程的。3 个线程与 Application.Run 和一堆其他后台工作线程一起运行。让所有线程正确关闭有点棘手,但我想我终于做对了。

但是当我们实际部署应用程序时,用户开始体验到应用程序不退出。有一个 System.Threading.Mutex 可以防止他们多次运行应用程序,因此他们必须进入任务管理器并杀死旧的,然后才能再次运行它。

在主线程退出之前,每个线程都会获得一个 Thread.Join,并且我将日志记录添加到我生成的每个线程中。根据日志,每一个启动的单线程也退出,主线程也退出。更奇怪的是,运行 SysInternals ProcessExplorer 显示应用程序退出时所有线程都消失了。如,有 0 个线程(托管或非托管),但进程仍在运行。

我无法在任何开发人员的计算机或我们的测试环境中重现这种情况,到目前为止,我只在 Windows XP(不是 Vista 或 Windows 7 或任何 Windows Server)上看到过这种情况。一个进程如何以 0 个线程继续运行?

编辑:

这里有更多细节。事件循环之一是托管 Win32 互操作 DLL,它使用 COM 对象与设备驱动程序对话。我将它放在自己的线程中,因为设备驱动程序对时间敏感,并且每当 UI 线程会阻塞很长时间(例如等待数据库调用完成)时,它都会干扰设备驱动程序。

所以我更改了代码,因此主线程将使用设备驱动程序线程执行 Thread.Join。这实际上导致应用程序锁定......它在加入完成后在 UI 线程上记录了更多调用,然后一切都停止了。如果设备断电,驱动程序永远不会启动,问题就会消失。所以看起来驱动程序必须负责保持应用程序的活动,即使在它应该被关闭之后也是如此。

4

3 回答 3

1

创建线程时,在它们上设置 IsBackground=true。当您的主 ui 线程/应用程序关闭时,所有创建的线程将自动关闭。

http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground.aspx

于 2010-04-23T16:26:37.553 回答
0

您的 Application.Run 调用的孩子是否可能没有终止?此外,究竟是什么导致应用程序退出 - 当所有线程终止时它会自动关闭(自动意味着您编写了一些代码来执行此操作),还是用户模仿?

我曾经遇到过一个问题,即我的“线程完成”事件代码中存在竞争条件,有时会导致您看到的结果。最后两个线程将同时完成,同时触发事件,每个事件都将确定它不是最后一个线程,因此应用程序将继续运行,即使线程计数为零。为了解决这个问题,我能够找到并消除竞争条件,但您也可以使用一个计时器,每隔一两秒检查一次,获取线程数,如果没有仍然打开,它会终止应用程序。

于 2010-04-23T16:07:00.917 回答
0

我们从来没有弄清楚根本的编程原因,但它是导致问题的特定驱动程序版本,升级到新驱动程序可以解决问题。

不幸的是,如果有一天其他人遇到类似的问题,这就是我能给出的所有答案......

于 2010-10-22T17:42:59.603 回答