Это то, что я обнаружил всего несколько дней назад, я получил подтверждение, что этот вопрос не ограничивается только моей машиной .
Самый простой способ воспроизвести его - запустить приложение 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 аварийно завершают работу одинаково.
- Код выхода не имеет значения.
- Вызов Thread.Sleep () перед вызовом Exit () не исправляет это.
- Это происходит в 64-разрядной версии Windows 8, и Windows 7, похоже, не подвержена такому же влиянию.
- Это должно быть относительно новое поведение, я не видел этого раньше. Я не вижу соответствующих обновлений, доставляемых через Центр обновления Windows , хотя история обновлений на моем компьютере больше не точна.
- Это грубо нарушающее поведение. Вы могли бы написать такой код в обработчике событий для AppDomain.UnhandledException, и он вылетает так же.
Мне особенно интересно, что вы могли бы сделать, чтобы избежать этой аварии. В частности, сценарий AppDomain.UnhandledException ставит меня в тупик; Есть не так много способов завершить программу .NET. Обратите внимание, что вызов Application.Exit () или Form.Close () недопустим в обработчике событий для UnhandledException, поэтому они не являются обходными путями.
ОБНОВЛЕНИЕ: Mehrdad указал, что поток финализатора мог быть частью проблемы. Я думаю, что вижу это, а также вижу некоторые свидетельства для 2-секундного тайм-аута, что CLR дает потоку финализатора завершить выполнение.
Финализатор находится внутри NativeWindow.ForceExitMessageLoop (). Там есть функция Win32 IsWindow (), которая примерно соответствует расположению кода, смещение 0x3c при просмотре машинного кода в 32-битном режиме. Похоже, что 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
Ханс сказал так!
Exit(0)
немного раньше, когда работал 64-битный Win7, изменение ExitCode
не помогло, теперь я использую его Process.GetCurrentProcess().Kill()
без проблем