【问题标题】:Why shouldn't I use Process.GetCurrentProcess().Kill() to exit my WinForm application?为什么我不应该使用 Process.GetCurrentProcess().Kill() 来退出我的 WinForm 应用程序?
【发布时间】:2010-10-11 05:19:22
【问题描述】:

现在,当用户想要退出我的应用程序时,我会做一些我必须做的事情(即断开与服务器的连接、保存用户数据...)然后我执行以下操作:

  • 使用布尔值退出我的所有主循环
  • 中止仍在运行的线程(通常是我的服务器轮询线程)
  • 请致电 Application.Exit();

这需要几秒钟才能退出,并且没有任何实际用途(所有内容都已保存在服务器上,所以我并不关心那里发生了什么)

如果我改用它,我会立即终止,没有我能想到的缺点:

 System.Diagnostics.Process.GetCurrentProcess().Kill();

我为什么不直接终止我的进程并让 CLR 删除 AppDomain ?

我知道仔细处理您的共享资源(IO 文件处理程序等)很重要(所以请不要回答这个问题:)),但是一旦完成,是否有真正的理由干净地退出我的应用程序?

【问题讨论】:

  • 我猜在这种情况下任何 finally 块都不会被处理,这可能会在将来其他人维护代码时导致意外的错误。
  • @Hosam:这是一个很好的观点。您为什么不将其发布为答案,以便对其进行投票?
  • @Brann:完成。感谢您的建议。

标签: .net termination


【解决方案1】:

杀死进程意味着 finally 块不会被执行,甚至可能不会执行 critical finalizer objects,这实际上可能很关键,并导致系统级别的资源泄漏。当其他人维护代码时,它还可能在将来导致意外的错误,因为他们(或您)将不得不扭头,每次他们编写 finally 块时都必须考虑它是否会被执行。

【讨论】:

  • 操作系统不应该仅仅因为一个进程被杀死而泄漏资源。但是这些 finally 块和终结器是一个好点。
  • @Qwertie 是的,但有时确实如此。例如,即使应用程序崩溃,相机也可能保持打开状态。这可能是驱动程序中的错误,但这也是“系统”的一部分。
【解决方案2】:

这确实是个好问题!

曾几何时(十多年前)我写了一个 VB6 应用程序,由于在 Web 服务器上使用的特定证书,WinINet OCX(或其他任何名称)中的一个已确认错误导致终止挂起交谈。

没有任何办法解决这个错误,我使用了 TerminateProcess,据我所知,这个应用程序已经在数千台机器上使用了好几年,但我从未听说过关于这个 hack 的任何问题!

【讨论】:

  • 然而我现在有一个测试用例,它因 Kill hack 而失败。它加载了骰子,确切地说明了进程何时被杀死,进程正在做什么,以及应该发生什么。这就是为什么 ACID 数据库要经过 极大的长度 来确保数据写入/可重放性 - 以便它们可以随时被粗暴地关闭而不会丢失数据。如果卡住的进程正在使用关键数据(当时或以后)进行蹲下,那么一定要对它进行核对;这真的和通过进程资源管理器杀死进程没有什么不同。
【解决方案3】:

首先,我认为您的意思是Process.Kill(),而不是Process.TerminateProcess()。其次,杀死进程只会把它撕掉。任何清理代码都不会执行,并且您的应用程序将没有机会取消终止(例如,如果用户有未保存的数据)。如果您对此感到满意,那就去吧。

【讨论】:

  • 其实就是 Process.GetCurrentProcess().Kill();我相应地修复了我的帖子。感谢您注意到它!:)
【解决方案4】:

请记住,如果您正在写入文件/网络流,您的写入可能会不完整。

如果您的应用程序已准备好以这种方式处理损坏的数据,那么没有理由不这样做。但是,如果您可以通过其他方式退出,我建议您这样做。

【讨论】:

    【解决方案5】:

    需要注意的是finalizers may actually be never executed,因此终止进程与跳过终结代码的任何其他原因没有太大区别,例如慢终结器或终结器抛出异常。

    总而言之,我不会担心关闭应用程序需要几秒钟,尤其是当它立即隐藏所有窗口并为用户“消失”时。但是,如果关闭需要几十秒和/或用户可能会再次执行应用程序并且它不支持多个实例,那么调用Process.Kill 可能是个好主意。

    我知道一些应用程序需要 ages 才能终止,我希望有一天他们会残忍地杀死自己,而不是让我,用户,这样做(在操作系统重新启动时尤其烦人) .

    【讨论】:

      【解决方案6】:

      使用无法捕获错误或泄漏的第三方库,有时在不引发崩溃 MessageBox 的情况下结束它的唯一方法是终止进程。

      【讨论】:

        【解决方案7】:

        为什么不使用System.Environment.Exit(int)?看起来你想这样做只是为了保存代码。对我来说,更清楚地看到对 Exit 的调用,并且您的关机将受到更多控制,Finalizers 和 Critical Finalizers 将运行。

        【讨论】:

        • Environment.Exit(int) 不保证在底层 appdomain 或本机代码跳转到 WER / ReportFault 系列函数时退出。即使 Kill() 也不是终止保证,因为内核级死锁会阻止进程退出,但 Kill 通常会立即终止,而 Exit 允许程序清理。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-19
        相关资源
        最近更新 更多