首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么Environment.Exit()不再终止程序?

为什么Environment.Exit()不再终止程序?
EN

Stack Overflow用户
提问于 2013-08-04 04:11:54
回答 4查看 30.8K关注 0票数 144

这是我几天前发现的,我从this question得到了确认,它不仅仅局限于我的机器。

重现它的最简单方法是启动Windows窗体应用程序,添加一个按钮并编写以下代码:

    private void button1_Click(object sender, EventArgs e) {
        MessageBox.Show("yada");
        Environment.Exit(1);         // Kaboom!
    }

执行Exit()语句后,程序会失败。在Windows窗体上,您会看到“创建窗口句柄时出错”。

启用非托管调试可以使所发生的事情变得更加清晰。COM模式循环正在执行,并允许传递WM_PAINT消息。在已处理的表单上,这是致命的。

到目前为止,我收集到的唯一事实是:

  • 它并不仅限于使用调试器运行。如果没有一个,这也会失败。同样糟糕的是,WER崩溃对话框显示了两次。
  • 它与进程的位数没有任何关系。wow64层是非常臭名昭著的,但是AnyCPU版本也会以同样的方式崩溃。
  • 它和.NET版本没有任何关系,4.5和3.5版本的崩溃也是一样的。
  • 在调用Thread.Sleep()之前退出代码没有修复它。
  • 在64位版本的Windows8上会发生这种情况,而Windows7似乎不会受到同样的影响。
  • 这应该是相对较新的行为,我以前没有见过这种情况。我没有看到通过Windows Update提供的相关更新,尽管更新历史在我的机器上不再准确。
  • 这是严重的破坏行为。您可以在AppDomain.UnhandledException的事件处理程序中编写如下代码,它也会以同样的方式崩溃。

我特别感兴趣的是,您可以做些什么来避免这种崩溃。特别是AppDomain.UnhandledException场景把我难倒了;终止.NET程序的方法并不多。请注意,调用Application.Exit()或Form.Close()在UnhandledException的事件处理程序中无效,因此它们不是解决方法。

更新: Mehrdad指出终结器线程可能是问题的一部分。我想我看到了这一点,也看到了CLR给终结器线程2秒超时来完成执行的一些证据。

终结器在NativeWindow.ForceExitMessageLoop()中。这里有一个IsWindow() Win32函数,它大致对应于在32位模式下查看机器代码时的代码位置,偏移量为0x3c。看起来IsWindow()是死锁的。我不能很好地跟踪内部的堆栈,但是调试器认为P/Invoke调用刚刚返回。这很难解释。如果你能得到一个更好的堆栈跟踪,那么我很乐意看到它。我的:

System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.ForceExitMessageLoop() + 0x3c bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Finalize() + 0x16 bytes
[Native to Managed Transition]
kernel32.dll!@BaseThreadInitThunk@12()  + 0xe bytes
ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes

ForceExitMessageLoop调用之上没有任何内容,已启用非托管调试器。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-08-17 21:51:11

我就这个问题联系了微软,这似乎得到了回报。至少我认为是这样的:)。虽然我没有从他们那里得到解决方案的确认,但Windows小组很难直接联系,我不得不使用中间人。

通过Windows update提供的更新解决了这个问题。崩溃前明显的2秒延迟不再存在,这强烈地表明IsWindow()死锁得到了解决。并且程序会干净可靠地关闭。该更新安装了Windows Defender、wdboot.sys、wdfilter.sys、tcpip.sys、rpcrt4.dll、uxtheme.dll、crypt32.dll和wintrust.dll的修补程序

Uxtheme.dll是个怪胎。它实现了Visual Styles主题API,并由该测试程序使用。我不能肯定,但我敢打赌这是问题的根源。C:\WINDOWS\system32中的副本版本号为6.2.9200.16660,创建于2013年8月14日,在我的机器上。

结案了。

票数 90
EN

Stack Overflow用户

发布于 2013-08-04 04:55:46

我不知道为什么它“不再”工作了,但我认为Environment.Exit会执行挂起的终结器。Environment.FailFast不需要。

这可能是(出于某种奇怪的原因)你有一些奇怪的挂起的终结器,这些终结器必须在之后运行,从而导致这种情况发生。

票数 54
EN

Stack Overflow用户

发布于 2013-08-04 04:42:10

这并不能解释为什么会发生这种情况,但我不会像您的示例那样在按钮事件处理程序中调用Environment.Exit -而是按照rene's answer中的建议关闭主窗体。

至于AppDomain.UnhandledException处理程序,也许您可以只设置Environment.ExitCode,而不是调用Environment.Exit

我不知道你在这里想要实现什么。为什么要从Windows窗体应用程序返回退出代码?通常,退出代码由控制台应用程序使用。

我特别感兴趣的是,您可以做些什么来避免这种崩溃,需要调用Environment.Exit()来阻止

对话框的显示。

你在Main方法中有try/catch吗?对于Windows窗体应用程序,我总是在消息循环和未处理的异常处理程序周围使用try/catch。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18036863

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档