이것은 며칠 전에 발견 한 것입니다 . 이 질문 에서 내 컴퓨터에만 국한되지 않는다는 확인을 받았습니다 .
이를 재현하는 가장 쉬운 방법은 Windows Forms 응용 프로그램을 시작하고 단추를 추가 한 후 다음 코드를 작성하는 것입니다.
private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("yada");
Environment.Exit(1); // Kaboom!
}
Exit () 문이 실행 된 후 프로그램이 실패합니다 . Windows Forms에서 "창 핸들 작성 오류"가 표시됩니다.
관리되지 않는 디버깅을 활성화하면 진행 상황이 어느 정도 명확 해집니다. COM의 모달 루프가 실행하고 WM_PAINT 메시지가 전달 될 수있다. 폐기 된 형태에 치명적입니다.
내가 지금까지 모은 유일한 사실은 다음과 같습니다.
- 디버거로 실행하는 것만으로는 제한되지 않습니다. 이것 없이도 실패합니다. 오히려 WER 크래시 대화 상자가 두 번 나타납니다 .
- 프로세스의 비트와 관련이 없습니다. wow64 레이어는 꽤 악명 높지만 AnyCPU 빌드는 같은 방식으로 충돌합니다.
- .NET 버전 4.5와 3.5는 같은 방식으로 충돌하지 않습니다.
- 종료 코드는 중요하지 않습니다.
- Exit ()를 호출하기 전에 Thread.Sleep ()를 호출해도 문제가 해결되지 않습니다.
- 이는 64 비트 버전의 Windows 8에서 발생하며 Windows 7은 동일한 방식으로 영향을받지 않는 것 같습니다.
- 이것은 비교적 새로운 행동이어야합니다. 이전에 본 적이 없었습니다. 내 컴퓨터에서 업데이트 기록이 더 이상 정확하지 않지만 Windows Update를 통해 제공되는 관련 업데이트 는 없습니다.
- 이것은 엄청나게 파괴적인 행동입니다. AppDomain.UnhandledException의 이벤트 처리기에서 이와 같은 코드를 작성하면 같은 방식으로 충돌합니다.
이 충돌을 피하기 위해 할 수있는 일에 특히 관심이 있습니다. 특히 AppDomain.UnhandledException 시나리오가 저를 방해합니다. .NET 프로그램을 종료하는 방법은 많지 않습니다. UnhandledException에 대한 이벤트 처리기에서는 Application.Exit () 또는 Form.Close () 호출이 유효하지 않으므로 해결 방법이 아닙니다.
업데이트 : Mehrdad는 finalizer 스레드가 문제의 일부일 수 있다고 지적했습니다. 나는 이것을보고 있다고 생각하고 CLR이 finalizer 스레드가 실행을 끝내게한다는 2 초 타임 아웃에 대한 증거를보고있다.
종료자는 NativeWindow.ForceExitMessageLoop () 안에 있습니다. 32 비트 모드에서 기계어 코드를 볼 때 코드 위치와 대략 0x3c 오프셋 인 IsWindow () Win32 함수가 있습니다. IsWindow ()가 교착 상태 인 것 같습니다. 내부에 대해 좋은 스택 추적을 얻을 수는 없지만 디버거는 P / Invoke 호출이 방금 반환 된 것으로 생각합니다 . 이것은 설명하기 어렵다. 더 나은 스택 추적을 얻을 수 있다면 그것을보고 싶습니다. 나의 것:
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 호출 이상은 없습니다.
This happens on the 64-bit version of Windows 8
Hans는 그렇게 말했습니다!
Exit(0)
64 비트 Win7에서 조금 전에 이런 종류의 동작이 발생했습니다 . 변경 ExitCode
은 Process.GetCurrentProcess().Kill()
문제없이 작동하는 데 도움이되지 않습니다.