Warum beendet Environment.Exit () das Programm nicht mehr?

Dies ist etwas, was ich vor ein paar Tagen entdeckt habe. Ich habe die Bestätigung bekommen, dass es nicht nur auf meine Maschine von beschränkt istdiese Frage.

Der einfachste Weg, dies zu wiederholen, besteht darin, eine Windows Forms-Anwendung zu starten, eine Schaltfläche hinzuzufügen und den folgenden Code zu schreiben:

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

Das Programm schlägt fehlnach dem Die Anweisung Exit () wird ausgeführt. In Windows Forms wird "Fehler beim Erstellen des Fensterhandles" angezeigt.

Wenn Sie das nicht verwaltete Debugging aktivieren, wird etwas klarer, was los ist. DasCOM Die modale Schleife wird ausgeführt und ermöglicht die Zustellung einer WM_PAINT-Nachricht. Das ist fatal bei einer entsorgten Form.

Die einzigen Fakten, die ich bisher gesammelt habe, sind:

Es ist nicht nur auf die Ausführung mit dem Debugger beschränkt. Dies scheitert auch ohne einen. Auch der WER-Absturzdialog wird eher schlecht angezeigtzweimal.Es hat nichts mit der Bissigkeit des Prozesses zu tun. Die wow64-Ebene ist ziemlich berüchtigt, aber ein AnyCPU-Build stürzt auf die gleiche Weise ab.Es hat nichts mit der .NET-Version zu tun, 4.5 und 3.5 stürzen auf die gleiche Weise ab.Der Exit-Code spielt keine Rolle.Das Aufrufen von Thread.Sleep () vor dem Aufrufen von Exit () behebt das Problem nicht.Dies geschieht unter der 64-Bit-Version von Windows 8, und Windows 7 scheint nicht auf die gleiche Weise betroffen zu sein.Dies sollte ein relativ neues Verhalten sein, das habe ich noch nie gesehen. Ich sehe keine relevanten Updates durchWindows Update, obwohl der Updateverlauf auf meinem Rechner nicht mehr korrekt ist.Dies bricht das Verhalten massiv. Sie würden Code wie diesen in eine Ereignisbehandlungsroutine für AppDomain.UnhandledException schreiben und er stürzt auf die gleiche Weise ab.

Ich bin besonders daran interessiert, was Sie möglicherweise tun können, um diesen Absturz zu vermeiden. Besonders das AppDomain.UnhandledException-Szenario überrascht mich. Es gibt nicht viele Möglichkeiten, ein .NET-Programm zu beenden. Beachten Sie, dass das Aufrufen von Application.Exit () oder Form.Close () in einem Ereignishandler für UnhandledException nicht gültig ist und daher keine Problemumgehung darstellt.

UPDATE: Mehrdad wies darauf hin, dass der Finalizer-Thread Teil des Problems sein könnte. Ich denke, ich sehe dies und sehe auch einige Beweise für das 2-Sekunden-Timeout, dass die CLR den Finalizer-Thread zum Beenden der Ausführung gibt.

Der Finalizer befindet sich in NativeWindow.ForceExitMessageLoop (). Dort gibt es eine IsWindow () Win32-Funktion, die in etwa der Codestelle entspricht, Offset 0x3c, wenn der Maschinencode im 32-Bit-Modus betrachtet wird. Es scheint, dass IsWindow () blockiert. Für die Interna kann ich jedoch keinen guten Stack-Trace erhalten, denkt der DebuggerP / Invoke Anruf ist gerade zurückgekehrt. Das ist schwer zu erklären. Wenn Sie einen besseren Stack-Trace erhalten, würde ich ihn gerne sehen. Bergwerk:

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

Nichts über dem ForceExitMessageLoop-Aufruf, nicht verwalteter Debugger aktiviert.