J'ai découvert ce phénomène il y a quelques jours et j'ai eu la confirmation qu'il n'était pas limité à ma machine grâce à cette question .
La façon la plus simple de le reproduire est de démarrer une application Winforms, d'ajouter un bouton et d'écrire ce code :
private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("yada");
Environment.Exit(1); // Kaboom!
}
Le programme échoue après l'instruction Exit() s'exécute. Sur Winforms, vous obtenez "Error creating window handle".
L'activation du débogage non géré permet de comprendre ce qui se passe. La boucle modale COM s'exécute et permet la délivrance d'un message WM_PAINT. C'est fatal sur un formulaire disposé.
Les seuls faits que j'ai recueillis jusqu'à présent sont :
- Ce n'est pas seulement limité à l'exécution avec le débogueur. Cela échoue également sans celui-ci. La boîte de dialogue de plantage WER s'affiche également de manière assez médiocre. deux fois .
- Cela n'a rien à voir avec le bitness du processus, la couche wow64 est assez connue mais une construction AnyCPU se plante de la même façon.
- Cela n'a rien à voir avec la version .NET, les versions 4.5 et 3.5 se plantent de la même façon.
- Le code de sortie n'a pas d'importance.
- Appeler Thread.Sleep() avant d'appeler Exit() ne résout pas le problème.
- Cela se produit sur la version 64 bits de Windows 8, Windows 7 ne semble pas être affecté de la même manière.
- Ce comportement doit être relativement nouveau, je ne l'ai jamais vu auparavant. Je ne vois aucune mise à jour pertinente fournie par Windows Update, bien que l'historique des mises à jour ne soit plus exact sur ma machine.
- Il s'agit d'une rupture flagrante du comportement, vous écrivez un code comme celui-ci dans un gestionnaire d'événement pour AppDomain.UnhandledException et il se plante de la même manière.
Je suis particulièrement intéressé par ce que vous pourriez faire pour éviter cet accident. En particulier, le scénario AppDomain.UnhandledException me laisse perplexe, il n'y a pas beaucoup de façons de mettre fin à un programme .NET. Veuillez noter que l'appel à Application.Exit() ou Form.Close() n'est pas valable dans un gestionnaire d'événements pour UnhandledException et qu'il ne s'agit donc pas de solutions de rechange.
MISE À JOUR : Mehrdad a signalé que le fil de discussion du finisseur pourrait faire partie du problème. Je pense que c'est ce que je vois, et je vois aussi des preuves du délai de 2 secondes que le CLR donne au thread finalizer pour terminer l'exécution.
Le finalisateur se trouve dans NativeWindow.ForceExitMessageLoop(). Il y a une fonction winapi IsWindow() qui correspond à peu près à l'emplacement du code, offset 0x3c en regardant le code machine en mode 32 bits. Il semble que IsWindow() soit en train de se bloquer. Je ne peux pas obtenir une bonne trace de la pile pour les internes cependant, le débogueur pense que l'appel pinvoke vient de retourner. C'est difficile à expliquer. Si vous pouvez obtenir une meilleure trace de pile, j'aimerais la voir. Le mien :
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
Rien au-dessus de l'appel ForceExitMessageLoop, débogueur non géré activé.