NullReferenceException без трассировки стека при перехвате SetConsoleCtrlHandler - PullRequest
7 голосов
/ 22 июля 2011

Используя код для перехвата события закрытия консоли из этого потока , я иногда получаю NullReferenceException без трассировки стека (в большинстве случаев я этого не делаю).Это происходит как в выпуске, так и в отладке, и «прерывание при возникновении исключения» не помогает (оно прерывается, но трассировка стека все еще пуста).Я никогда не получаю это исключение, когда я обычно выхожу из приложения (которое нажимает Enter и, таким образом, освобождает Console.ReadLine).Журнал событий приложения содержит 2 записи:

Приложение: MyApp.exe Framework Версия: v4.0.30319 Описание: Процесс был прерван из-за необработанного исключения.Сведения об исключении: стек System.NullReferenceException:

И:

Имя ошибочного приложения: Gateway.exe, версия: 1.0.0.0, отметка времени: 0x4e284101 Имя ошибочного модуля:неизвестно, версия: 0.0.0.0, отметка времени: 0x00000000 Код исключения: 0xc0000005 Смещение ошибки: 0x004d41ce Идентификатор ошибочного процесса: 0xf00 Время запуска ошибочного приложения: 0x01cc47b827e19a6e Путь ошибочного приложения: C: \ dev \ MyApp.exe Путь к ошибочному модулю: неизвестен Идентификатор отчета: 689c1caa-b3ab-11e0-ba1b-00247e777f12

Google обнаружил ошибок и проблем с SetConsoleCtrlHandler, поэтому мне интересно, если этоэто проигранная битва.

Ответы [ 2 ]

12 голосов
/ 22 июля 2011

Наиболее типичная проблема с таким кодом - не сохранение ссылки на экземпляр делегата.Тот, который вы передаете в качестве первого аргумента SetConsoleCtrlHandler ().Сборщик мусора не может видеть ссылки, хранящиеся на объекте делегата неуправляемым кодом.Таким образом, это, в конечном счете, будет бомбить при запуске сборщика мусора:

 SetConsoleCtrlHandler(Handler, true);

, что точно так же, как

 SetConsoleCtrlHandler(new EventHandler(Handler), true);

, при условии, что вы использовали типы в связанном коде.Автор этого кода тщательно избежал этой проблемы, сделав _handler статической переменной.В отличие от временного экземпляра делегата, который создается двумя предыдущими строками кода.Хранение его в статической переменной гарантирует, что на него будут ссылаться в течение всей жизни программы.Правильное действие в данном конкретном случае, поскольку вы на самом деле интересуетесь событиями до завершения программы.

0 голосов
/ 19 апреля 2012

Для тел vb.net, которые борются с этим, мой код ...

'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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...