Environment.Exit()和Application.Shutdown()有什么区别?

28

有时候当我调用Application.Shutdown关闭应用程序时,虽然UI已经关闭了,但进程仍在运行。如何关闭应用程序并关闭所有线程? Environment.Exit()能否关闭所有线程?或者我们应该调用Win32 API的TerminateThread来实现?

3个回答

24

Environment.Exit() 是一种更加强制性的关闭应用程序的方式。但是通常来说,如果您需要杀死应用程序以使其关闭,那么我认为您正在错误地看待问题。

您应该查找其他线程为何无法正常关闭而优雅地关闭它们。

您可以查看主窗体上的FormClosing事件并关闭阻止应用程序关闭的任何资源。

以下是我发现资源导致应用程序无法关闭的方法:

  1. 在调试模式下启用显示线程。(这将允许您查看应用程序正在运行的所有线程。)
  2. 以不正确的方式关闭应用程序。
  3. 在 Visual Studio 中按暂停按钮。
  4. 查看线程列表,并单击它们以查看它们所挂起的代码。现在,您可以看到哪些资源阻止了应用程序关闭,然后在 FormClosing 事件中关闭/释放它们。
  5. 重复此操作直至应用程序正确关闭 :)

请注意,调试模式下的线程列表将显示一些您无法控制的已运行线程。这些线程很少有名称,当您单击它们时,您会收到一条消息,指出未找到符号。这些线程可以安全地忽略。

确保应用程序优雅地关闭的原因之一是某些资源(比如FileStream)尚未完成工作,因此使用某些API来强制退出可能会导致各种“随机”的问题,例如设置/数据文件未被写入等。


谢谢您的回复,我已经尝试调用“Application.Shutdown”方法来结束进程,但是有时候进程并没有被关闭。我也尝试了您提供的方法来找出哪个线程还在运行,但是无法重现这个错误。 - Cooper.Wu

10

哦,太棒了。我不知道你可以做#2。 - Joel
2
IsBackground 对我解决了这个问题。非常有用,惊讶它不是更广为人知的。 - SouthShoreAK
哲学问题(或者可能是愚蠢的问题):如果我们永远不应该调用它,为什么它还存在? - alzaimar
@alzaimar:该函数存在是因为有极其特殊的情况可能被迫调用它。这些特殊情况在TerminateThread函数文档的备注部分中有详细说明。我要补充的是,即使在这些情况下,如果代码编写得更好,也可以避免使用该函数。因此,该函数之所以仍然存在可能是由于“历史”和“兼容性”。 - gog

4
如Shay所说,永远不要调用TerminateThread。TerminateThread只会杀死一个线程而不让它自我清理,这可能会导致进程中其他线程死锁和损坏。
另一方面,TerminateProcess将杀死整个进程并让操作系统进行清理,这是关闭进程的最快方法 - 您只需要确保您没有持有任何操作系统无法清理的资源(在调用TerminateProcess之前关闭窗口也有帮助)。
我认为(但我还没有检查过),Environemnt.Exit调用TerminateProcess。
Application.Shutdown非常不同,它不会立即终止进程 - 它发送所有关闭和关闭通知,并等待应用程序的所有窗口和线程自行关闭。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接