NullReferenceException sans trace de stack lors de l’accrochage de SetConsoleCtrlHandler

En utilisant du code pour accrocher l’événement de fermeture de la console à partir de ce fil , je reçois parfois une NullReferenceException sans stacktrace (la plupart du temps, ce n’est pas le cas). Cela se produit à la fois lors de la publication et du débogage, et “interrompre lorsqu’une exception est générée” n’aide pas (cela se rompt, mais la trace de la stack est toujours vide). Je ne reçois jamais cette exception lorsque je quitte mon application normalement (ce qui clique sur entrée et libère ainsi un Console.ReadLine ). Le journal des événements de l’application contient 2 entrées:

Application: MyApp.exe Framework Version: v4.0.30319 Description: le processus a été arrêté en raison d’une exception non gérée. Informations sur les exceptions: System.NullReferenceException Stack:

Et:

Nom de l’application défaillante: Gateway.exe, version: 1.0.0.0, horodatage: 0x4e284101 Nom du module défaillant: inconnu, version: 0.0.0.0, horodatage: 0x00000000 Code d’exception: 0xc0000005 Correction du défaut: 0x004d41ce ID du processus défaillant: 0xf00 au démarrage de l’application défaillante time: 0x01cc47b827e19a6e Chemin d’access de l’application défaillante: C: \ dev \ MyApp.exe Chemin d’access du module défaillant: inconnu ID du rapport: 689c1caa-b3ab-11e0-ba1b-00247e777f12

Google a révélé des bogues et des problèmes avec SetConsoleCtrlHandler . Je me demande donc s’il s’agit d’une bataille perdue.

Le problème le plus typique avec un code comme celui-là n’est pas de garder une référence à l’instance de délégué. Celui que vous passez comme premier argument à SetConsoleCtrlHandler (). Le garbage collector ne peut pas voir les références détenues par un code non géré sur un object délégué. Donc, cela finira par exploser lorsque le ramasse-miettes s’exécute:

  SetConsoleCtrlHandler(Handler, true); 

qui est exactement la même chose que

  SetConsoleCtrlHandler(new EventHandler(Handler), true); 

en supposant que vous avez utilisé les types dans le code lié. L’auteur de ce code a soigneusement évité ce problème en faisant de _handler une variable statique. Par opposition à l’instance de délégué temporaire créée par les deux lignes de code précédentes. Le stockage dans une variable statique garantit qu’il rest référencé pendant toute la durée du programme. La bonne chose à faire dans ce cas particulier puisque vous êtes réellement intéressé par les événements jusqu’à la fin du programme.

Pour les bods de vb.net qui luttent avec cela, mon code est …

 'declaration Private Declare Function SetConsoleCtrlHandler Lib "kernel32" (ByVal handlerRoutine As ConsoleEventDelegate, ByVal add As Boolean) As Boolean Public Delegate Function ConsoleEventDelegate(ByVal [event] As ConsoleEvent) As Boolean 'The close function... Public Function Application_ConsoleEvent(ByVal [event] As ConsoleEvent) As Boolean Console.WriteLine("We're closing it all down: ") Return False End Function 'creating the handler. If Not SetConsoleCtrlHandler(New ConsoleEventDelegate(AddressOf Application_ConsoleEvent), True) Then Console.WriteLine("Unable to install console event handler.") Exit Sub End If