Dlaczego Environment.Exit () nie kończy już programu?
To jest coś, co odkryłem kilka dni temu, otrzymałem potwierdzenie, że nie ogranicza się tylko do mojego komputerato pytanie.
Najprostszym sposobem na ponowną zmianę jest uruchomienie aplikacji Windows Forms, dodanie przycisku i napisanie tego kodu:
private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("yada");
Environment.Exit(1); // Kaboom!
}
Program nie działapo wykonywana jest instrukcja Exit (). W Windows Forms pojawia się komunikat „Błąd podczas tworzenia uchwytu okna”.
Włączenie niezarządzanego debugowania sprawia, że jest jasne, co się dzieje. TheCOM pętla modalna jest wykonywana i umożliwia dostarczenie komunikatu WM_PAINT. To jest śmiertelne na usuniętej formie.
Jedyne fakty, które do tej pory zebrałem, to:
Nie ogranicza się tylko do uruchamiania z debugerem. To również nie powiedzie się bez jednego. Raczej źle, pojawia się okno dialogowe awarii WERdwa razy.Nie ma to nic wspólnego ze świadkiem tego procesu. Warstwa wow64 jest dość znana, ale kompilacja AnyCPU ulega awarii w ten sam sposób.Nie ma to nic wspólnego z awarią wersji .NET, 4.5 i 3.5 w ten sam sposób.Kod wyjścia nie ma znaczenia.Wywołanie Thread.Sleep () przed wywołaniem Exit () nie rozwiązuje tego.Dzieje się tak w 64-bitowej wersji systemu Windows 8, a system Windows 7 nie wydaje się mieć takiego samego wpływu.To powinno być stosunkowo nowe zachowanie, nie widziałem tego wcześniej. Nie widzę żadnych istotnych aktualizacjiAktualizacja systemu Windows, chociaż historia aktualizacji nie jest już dokładna na moim komputerze.Jest to rażąco łamliwe zachowanie. Możesz napisać kod w ten sposób w procedurze obsługi zdarzeń dla AppDomain.UnhandledException i zawiesza się on w ten sam sposób.Jestem szczególnie zainteresowany tym, co możesz zrobić, aby uniknąć tego wypadku. Szczególnie mnie niepokoi scenariusz AppDomain.UnhandledException; nie ma wielu sposobów na zakończenie programu .NET. Należy pamiętać, że wywołanie Application.Exit () lub Form.Close () nie jest poprawne w procedurze obsługi zdarzeń dla UnhandledException, więc nie są to obejścia.
AKTUALIZACJA: Mehrdad zauważył, że wątek finalizatora może być częścią problemu. Myślę, że widzę to i widzę również dowody na 2-sekundowy limit czasu, który CLR daje wątkowi finalizatora zakończenie wykonywania.
Finalizator znajduje się wewnątrz NativeWindow.ForceExitMessageLoop (). Jest tam funkcja IsWindow () Win32, która w przybliżeniu odpowiada lokalizacji kodu, przesunięciu 0x3c, gdy patrzymy na kod maszynowy w trybie 32-bitowym. Wydaje się, że IsWindow () jest zakleszczeniem. Nie mogę jednak uzyskać dobrego śledzenia stosu dla elementów wewnętrznych, jednak debuger myśliP / Invoke połączenie właśnie wróciło. Trudno to wyjaśnić. Jeśli możesz uzyskać lepszy ślad stosu, chciałbym go zobaczyć. Mój:
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
Nic ponad wywołanie ForceExitMessageLoop, włączony niezarządzany debugger.