使用代码挂钩来自this thread的控制台关闭事件,我有时会得到一个没有堆栈跟踪的NullReferenceException
(大部分时间我没有)。它发生在发布和调试中,并且“抛出异常时中断”没有帮助(它中断,但堆栈跟踪仍为空)。当我正常退出我的应用程序时,我从未得到此异常(这是命中输入并因此释放Console.ReadLine
)。应用程序事件日志有两个条目:
应用程序:MyApp.exe Framework版本:v4.0.30319描述: 由于未处理的异常,该过程终止。例外 信息:System.NullReferenceException Stack:
和
错误应用程序名称:Gateway.exe,版本:1.0.0.0,时间戳: 0x4e284101错误模块名称:未知,版本:0.0.0.0,时间 标记:0x00000000异常代码:0xc0000005故障偏移:0x004d41ce 错误进程id:0xf00错误应用程序启动时间: 0x01cc47b827e19a6e故障应用程序路径: C:\ dev \ MyApp.exe错误模块路径: 未知报道编号:689c1caa-b3ab-11e0-ba1b-00247e777f12
Google已向SetConsoleCtrlHandler
透露了一些bugs和issues,所以我想知道这是否是一场失败的战斗。
答案 0 :(得分:11)
代码之类的最典型问题是不保留对委托实例的引用。您作为SetConsoleCtrlHandler()的第一个参数传递的那个。垃圾收集器无法通过非托管代码查看对委托对象的引用。因此,当垃圾收集器运行时,这最终会爆炸:
SetConsoleCtrlHandler(Handler, true);
与
完全相同 SetConsoleCtrlHandler(new EventHandler(Handler), true);
假设您使用了链接代码中的类型。该代码的作者通过将_handler设为静态变量来仔细避免此问题。与前两行代码创建的临时委托实例相反。将其存储在静态变量中可确保在程序的生命周期内保持引用。在这种特殊情况下要做的正确的事情,因为你实际上对程序结束之前的事件感兴趣。
答案 1 :(得分:0)
对于正在努力解决这个问题的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