Это то, что я обнаружил всего несколько дней назад, я получил подтверждение, что этот вопрос не ограничивается только моей машиной .
Самый простой способ воспроизвести его - запустить приложение 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()
без проблемОтветы:
Я связался с Microsoft по поводу этой проблемы, и это, казалось, окупилось. По крайней мере, я хотел бы думать, что это сделал :). Хотя я не получил от них подтверждения решения, с группой Windows сложно связаться напрямую, и мне пришлось использовать посредника.
Обновление, доставленное через Центр обновления Windows, решило проблему. Заметная 2-секундная задержка перед сбоем больше не присутствует, что настоятельно рекомендует устранить тупик IsWindow (). И программа выключается чисто и надежно. Обновление установило исправления для Защитника Windows, wdboot.sys, wdfilter.sys, tcpip.sys, rpcrt4.dll, uxtheme.dll, crypt32.dll и wintrust.dll.
Uxtheme.dll странная утка. Он реализует API тем Visual Styles и используется этой тестовой программой. Я не могу быть уверен, но мои деньги на это как источник проблемы. Копия в C: \ WINDOWS \ system32 имеет номер версии 6.2.9200.16660, созданный 14 августа 2013 года на моей машине.
Дело закрыто.
источник
Я не знаю, почему это не работает "больше" , но я думаю, что
Environment.Exit
выполняет ожидающие финализаторы.Environment.FailFast
не делает.Возможно, (по какой-то причудливой причине) у вас есть странные ожидающие финализаторы, которые должны запускаться позже, вызывая это.
источник
NativeWindow.ForceExitMessageLoop
застрял в управляемом или неуправляемом коде? Это даже застряло, или это занято - ожидание или ожидание сообщения или чего-то еще?Это не объясняет, почему это происходит, но я бы не стал вызывать
Environment.Exit
обработчик событий кнопки, как ваш пример - вместо этого закройте основную форму, как это предлагается в ответе Рене .Что касается
AppDomain.UnhandledException
обработчика, может быть, вы могли бы просто установитьEnvironment.ExitCode
вместо вызоваEnvironment.Exit
.Я не уверен, что вы пытаетесь достичь здесь. Почему вы хотите вернуть код выхода из приложения Windows Forms? Обычно коды выхода используются консольными приложениями.
Есть ли у вас попробовать / поймать в методе Main? Для приложений Windows Forms у меня всегда есть попытка / зацепка вокруг цикла сообщений, а также обработчиков необработанных исключений.
источник
Application.Exit
вместоEnvironment.Exit
.Я нашел ту же проблему в нашем приложении, мы решили ее с помощью следующей конструкции:
источник