Isso é algo que eu descobri há apenas alguns dias, e recebi a confirmação de que não está limitado apenas à minha máquina com essa pergunta .
A maneira mais fácil de reproduzi-lo é iniciando um aplicativo Windows Forms, adicione um botão e escreva este código:
private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("yada");
Environment.Exit(1); // Kaboom!
}
O programa falha após a execução da instrução Exit (). No Windows Forms, você recebe "Erro ao criar identificador de janela".
A ativação da depuração não gerenciada torna um pouco claro o que está acontecendo. O loop modal COM está em execução e permite que uma mensagem WM_PAINT seja entregue. Isso é fatal em um formulário descartado.
Os únicos fatos que reuni até agora são:
- Não se limita apenas à execução com o depurador. Isso também falha sem um. Um tanto ruim quanto, a caixa de diálogo de falha do WER aparece duas vezes .
- Não tem nada a ver com o testemunho do processo. A camada wow64 é bastante notória, mas uma compilação AnyCPU falha da mesma maneira.
- Não tem nada a ver com a versão .NET, 4.5 e 3.5 travar da mesma maneira.
- O código de saída não importa.
- Chamar Thread.Sleep () antes de chamar Exit () não o corrige.
- Isso acontece na versão de 64 bits do Windows 8 e o Windows 7 não parece ser afetado da mesma maneira.
- Este deve ser um comportamento relativamente novo, eu nunca vi isso antes. Não vejo atualizações relevantes fornecidas pelo Windows Update , embora o histórico de atualizações não seja mais preciso na minha máquina.
- Este é um comportamento grosseiramente violento. Você escreveria um código como esse em um manipulador de eventos para AppDomain.UnhandledException e ele trava da mesma maneira.
Estou particularmente interessado no que você poderia fazer para evitar esse acidente. Particularmente, o cenário AppDomain.UnhandledException me surpreende; não há muitas maneiras de encerrar um programa .NET. Observe que chamar Application.Exit () ou Form.Close () não é válido em um manipulador de eventos para UnhandledException, portanto, não são soluções alternativas.
ATUALIZAÇÃO: Mehrdad apontou que o encadeamento do finalizador pode ser parte do problema. Eu acho que estou vendo isso e também estou vendo algumas evidências pelo tempo limite de 2 segundos de que o CLR fornece ao thread do finalizador para concluir a execução.
O finalizador está dentro de NativeWindow.ForceExitMessageLoop (). Existe uma função IsWindow () Win32 que corresponde aproximadamente à localização do código, desloca 0x3c ao olhar o código da máquina no modo de 32 bits. Parece que IsWindow () está em um impasse. No entanto, não consigo obter um bom rastreamento de pilha para os internos, o depurador acha que a chamada P / Invoke acabou de retornar. Isso é difícil de explicar. Se você pode obter um melhor rastreamento de pilha, eu adoraria vê-lo. Meu:
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
Nada acima da chamada ForceExitMessageLoop, o depurador não gerenciado ativado.
This happens on the 64-bit version of Windows 8
Hans disse isso!Exit(0)
um pouco atrás, com alguns 64bit Win7, mudandoExitCode
não ajudou usando agoraProcess.GetCurrentProcess().Kill()
sem qualquer problema ele funcionaRespostas:
Entrei em contato com a Microsoft sobre esse problema e isso parecia ter valido a pena. Pelo menos eu gostaria de pensar que sim :). Embora eu não tenha recebido uma confirmação de uma resolução deles, é difícil entrar em contato diretamente com o grupo Windows e eu tive que usar um intermediário.
Uma atualização entregue pelo Windows Update resolveu o problema. O atraso perceptível de 2 segundos antes da falha não está mais presente, sugerindo fortemente que o bloqueio do IsWindow () foi resolvido. E o programa é encerrado de forma limpa e confiável. A atualização instalou os patches para Windows Defender, wdboot.sys, wdfilter.sys, tcpip.sys, rpcrt4.dll, uxtheme.dll, crypt32.dll e wintrust.dll
Uxtheme.dll é o estranho-out. Ele implementa a API de temas do Visual Styles e é usado por este programa de teste. Não tenho certeza, mas meu dinheiro está nessa como a fonte do problema. A cópia em C: \ WINDOWS \ system32 possui o número da versão 6.2.9200.16660, criada em 14 de agosto de 2013 na minha máquina.
Caso encerrado.
fonte
Não sei por que não funciona "mais" , mas acho que
Environment.Exit
executa finalizadores pendentes.Environment.FailFast
não.Pode ser que (por algum motivo bizarro) você tenha finalizadores pendentes estranhos que devem ser executados posteriormente, fazendo com que isso aconteça.
fonte
NativeWindow.ForceExitMessageLoop
parada no código gerenciado ou não gerenciado? É mesmo preso, ou está ocupado esperando ou esperando por uma mensagem ou outra coisa?Isso não explica por que está acontecendo, mas eu não chamaria
Environment.Exit
um manipulador de eventos de botão como o seu exemplo - em vez disso, feche o formulário principal conforme sugerido na resposta de rene .Quanto a um
AppDomain.UnhandledException
manipulador, talvez você possa apenas definir, emEnvironment.ExitCode
vez de ligarEnvironment.Exit
.Não tenho certeza do que você está tentando alcançar aqui. Por que você deseja retornar um código de saída de um aplicativo Windows Forms? Normalmente, os códigos de saída são usados pelos aplicativos de console.
Você tem uma tentativa / captura no método Main? Para aplicativos Windows Forms, eu sempre tenho um try / catch em torno do loop de mensagens, bem como os manipuladores de exceção não manipulados.
fonte
Application.Exit
vez deEnvironment.Exit
.Encontrei o mesmo problema em nosso aplicativo, resolvemos com a seguinte construção:
fonte