Dies ist etwas, das ich erst vor ein paar Tagen entdeckt habe. Ich habe durch diese Frage die Bestätigung erhalten, dass es nicht nur auf meine Maschine beschränkt ist .
Der einfachste Weg, dies zu reproduzieren, besteht darin, eine Windows Forms-Anwendung zu starten, eine Schaltfläche hinzuzufügen und diesen Code zu schreiben:
private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("yada");
Environment.Exit(1); // Kaboom!
}
Das Programm schlägt fehl, nachdem die Anweisung Exit () ausgeführt wurde. Unter Windows Forms wird "Fehler beim Erstellen des Fensterhandles" angezeigt.
Durch Aktivieren des nicht verwalteten Debuggens wird deutlich, was los ist. Die COM- Modalschleife wird ausgeführt und ermöglicht die Zustellung einer WM_PAINT-Nachricht. Das ist auf einer entsorgten Form fatal.
Die einzigen Fakten, die ich bisher gesammelt habe, sind:
- Es ist nicht nur auf die Ausführung mit dem Debugger beschränkt. Dies schlägt auch ohne fehl. Eher schlecht wird der WER-Absturzdialog auch zweimal angezeigt .
- Es hat nichts mit der Bitterkeit 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 in gleicher Weise betroffen zu sein.
- Dies sollte ein relativ neues Verhalten sein, das habe ich noch nie gesehen. Ich sehe keine relevanten Updates, die über Windows Update bereitgestellt werden , obwohl der Update-Verlauf auf meinem Computer nicht mehr korrekt ist.
- Dies ist ein grob brechendes Verhalten. Sie würden Code wie diesen in einen Ereignishandler 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önnten, um diesen Absturz zu vermeiden. Besonders das Szenario AppDomain.UnhandledException macht mich fertig; 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 Problemumgehungen 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 dem Finalizer-Thread die Ausführung gibt.
Der Finalizer befindet sich in NativeWindow.ForceExitMessageLoop (). Dort gibt es eine IsWindow () Win32-Funktion, die in etwa der Codeposition entspricht und 0x3c versetzt, wenn der Maschinencode im 32-Bit-Modus betrachtet wird. Es scheint, dass IsWindow () blockiert. Ich kann jedoch keine gute Stapelverfolgung für die Interna erhalten. Der Debugger glaubt, dass der P / Invoke- Aufruf gerade zurückgegeben wurde. Das ist schwer zu erklären. Wenn Sie eine bessere Stapelverfolgung erhalten können, würde ich sie 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.
This happens on the 64-bit version of Windows 8
Hans hat es gesagt!Exit(0)
vor einiger Zeit mit 64-Bit-Win7, Ändern, festgestelltExitCode
hat jetzt nicht geholfen, esProcess.GetCurrentProcess().Kill()
ohne Probleme zu verwendenAntworten:
Ich habe Microsoft wegen dieses Problems kontaktiert und das schien sich ausgezahlt zu haben. Zumindest würde ich gerne glauben, dass es so ist :). Obwohl ich keine Bestätigung einer Lösung von ihnen erhalten habe, ist es schwierig, die Windows-Gruppe direkt zu kontaktieren, und ich musste einen Vermittler verwenden.
Ein über Windows Update bereitgestelltes Update hat das Problem behoben. Die spürbare Verzögerung von 2 Sekunden vor dem Absturz ist nicht mehr vorhanden, was stark darauf hindeutet, dass der IsWindow () - Deadlock behoben wurde. Und das Programm fährt sauber und zuverlässig herunter. Das Update installierte Patches für Windows Defender, wdboot.sys, wdfilter.sys, tcpip.sys, rpcrt4.dll, uxtheme.dll, crypt32.dll und wintrust.dll
Uxtheme.dll ist die ungerade Ente. Es implementiert die Visual Styles-Themen-API und wird von diesem Testprogramm verwendet. Ich kann nicht sicher sein, aber mein Geld ist dafür die Ursache des Problems. Die Kopie in C: \ WINDOWS \ system32 hat die Versionsnummer 6.2.9200.16660, die am 14. August 2013 auf meinem Computer erstellt wurde.
Fall abgeschlossen.
quelle
Ich weiß nicht, warum es "nicht mehr" funktioniert , aber ich denke, es werden
Environment.Exit
ausstehende Finalizer ausgeführt.Environment.FailFast
nicht.Es kann sein, dass Sie (aus irgendeinem bizarren Grund) seltsame ausstehende Finalizer haben, die anschließend ausgeführt werden müssen, wodurch dies geschieht.
quelle
NativeWindow.ForceExitMessageLoop
in verwaltetem oder nicht verwaltetem Code zu stecken? Steckt es überhaupt fest oder wartet es auf eine Nachricht oder etwas anderes?Dies erklärt nicht, warum es passiert, aber ich würde keinen
Environment.Exit
Button-Event-Handler wie Ihr Beispiel aufrufen - schließen Sie stattdessen das Hauptformular, wie in Renes Antwort vorgeschlagen .Was einen
AppDomain.UnhandledException
Handler betrifft, könnten Sie vielleicht einfach einstellen,Environment.ExitCode
anstatt anzurufenEnvironment.Exit
.Ich bin mir nicht sicher, was Sie hier erreichen wollen. Warum möchten Sie einen Exit-Code aus einer Windows Forms-Anwendung zurückgeben? Normalerweise werden Exit-Codes von Konsolenanwendungen verwendet.
Haben Sie einen Versuch / Fang in der Hauptmethode? Für Windows Forms-Anwendungen habe ich immer einen Versuch / Fang um die Nachrichtenschleife sowie die nicht behandelten Ausnahmebehandlungsroutinen.
quelle
Application.Exit
stattdessen anrufen sollstEnvironment.Exit
.Ich habe das gleiche Problem in unserer App gefunden, wir haben es mit dem folgenden Konstrukt gelöst:
quelle