这是我几天前发现的东西,我从 这个问题得到确认,它不仅仅局限于我的机器。
最简单的复制方法是启动一个 Windows 窗体应用程序,添加一个按钮并编写以下代码:
private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("yada");
Environment.Exit(1); // Kaboom!
}
程序失败 之后的 Exit ()语句执行。在 Windows 窗体你得到“错误创建窗口句柄”。
启用非托管调试可以在一定程度上清楚发生了什么。COM模式循环正在执行,并允许传递 WM _ PAINT 消息。这对已处理的尸体来说是致命的。
到目前为止,我收集到的唯一事实是:
我特别感兴趣的是你能做些什么来避免这次坠机。尤其是 AppDomain。方案难倒了我; 没有很多方法可以终止。NET 程序。请注意,调用应用程序。出口()或表格。Close ()在 UnhandledException 的事件处理程序中无效,因此它们不是解决方案。
更新: Mehrdad 指出终结器线程可能是问题的一部分。我想我看到了这一点,并且也看到了一些证据,表明 CLR 给终结器线程提供了2秒钟的超时来完成执行。
终结器位于 NativeWindow 内部。ForceExitMessageLoop ().这里有一个 IsWindow () Win32函数,它大致对应于代码位置,在32位模式下查看机器代码时偏移量为0x3c。看起来 IsWindow ()是死锁的。我不能得到一个很好的内部堆栈跟踪,然而,调试器认为 请求调用刚刚返回。这很难解释。如果你能得到一个更好的堆栈跟踪,然后我很乐意看到它。我的:
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 调用之上没有任何内容。