To jest coś, co odkryłem zaledwie kilka dni temu, otrzymałem potwierdzenie, że nie ogranicza się to tylko do mojej maszyny z tego pytania .
Najłatwiejszym sposobem odtworzenia tego 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 kończy się niepowodzeniem po wykonaniu instrukcji Exit (). W Windows Forms pojawia się komunikat „Błąd podczas tworzenia uchwytu okna”.
Włączenie niezarządzanego debugowania sprawia, że jest nieco jasne, co się dzieje. COM pętla modalna jest wykonywany i pozwala na wiadomość WM_PAINT mają być dostarczone. To śmiertelne w przypadku wyrzuconej postaci.
Jedyne fakty, które do tej pory zebrałem, to:
- Nie ogranicza się tylko do uruchomienia z debugerem. To również się nie powiedzie bez jednego. Raczej kiepsko, okno dialogowe awarii WER pojawia się dwukrotnie .
- Nie ma to nic wspólnego z drobiazgowością procesu. Warstwa wow64 jest dość znana, ale kompilacja AnyCPU ulega awarii w ten sam sposób.
- Nie ma to nic wspólnego z tą samą awarią wersji .NET, 4.5 i 3.5.
- Kod wyjścia nie ma znaczenia.
- Wywołanie Thread.Sleep () przed wywołaniem Exit () nie naprawia tego.
- Dzieje się tak w 64-bitowej wersji systemu Windows 8 i wydaje się, że nie ma to takiego samego wpływu na system Windows 7.
- To powinno być stosunkowo nowe zachowanie, nie widziałem tego wcześniej. Nie widzę odpowiednich aktualizacji dostarczanych za pośrednictwem usługi Windows Update , chociaż historia aktualizacji nie jest już dokładna na moim komputerze.
- To jest rażąco łamiące zachowanie. Możesz napisać taki kod w procedurze obsługi zdarzeń dla AppDomain.UnhandledException i ulega awarii w ten sam sposób.
Jestem szczególnie zainteresowany tym, co możesz zrobić, aby uniknąć tej awarii. Szczególnie scenariusz AppDomain.UnhandledException mnie przytłacza; 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ą one obejściem.
UPDATE: Mehrdad wskazał, ż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, że CLR daje wątek finalizatora do zakończenia wykonywania.
Finalizator znajduje się w NativeWindow.ForceExitMessageLoop (). Jest tam funkcja IsWindow () Win32, która z grubsza odpowiada lokalizacji kodu, przesunięcie 0x3c podczas patrzenia na kod maszynowy w trybie 32-bitowym. Wygląda na to, że IsWindow () jest zakleszczona. Nie mogę uzyskać dobrego śladu stosu dla elementów wewnętrznych, jednak debuger uważa, że wywołanie P / Invoke właśnie zostało zwrócone. Trudno to wyjaśnić. Jeśli możesz uzyskać lepszy ślad stosu, chciałbym to zobaczyć. Kopalnia:
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 powyżej wywołania ForceExitMessageLoop, włączony niezarządzany debugger.
This happens on the 64-bit version of Windows 8
Hans tak powiedział!
Exit(0)
trochę temu z jakimś 64-bitowym Win7, zmiana ExitCode
nie pomogła teraz, używając Process.GetCurrentProcess().Kill()
bez problemu, działa