我正在调查由Win32异常导致的我的应用程序中的一些崩溃,我已经缩小了,它必须在我的应用程序中处理EventLog.EntryWrittenEventHandler事件处理程序的线程池中发生.我这样设置:
// Create the event log monitor eventLog.Log = "Application"; eventLog.EnableRaisingEvents = true; eventLog.EntryWritten += new EntryWrittenEventHandler(EventLogMonitor);
EventLogMonitor是我的事件的处理程序.我想知道有谁有任何想法,我可以找出导致这个例外的原因.看起来要监听一个ThreadPoolWaitOrTimerCallback的事件,它不会有任何我的代码,如果发生异常,我只是看不到如何处理这个问题.任何帮助真的很感激!
这是WinDBG中的!clrstack的输出:
0:008> !clrstack OS Thread Id: 0x106c (8) ESP EIP 049df1c8 7756f871 [HelperMethodFrame: 049df1c8] 049df26c 73ce6fa0 System.Diagnostics.EventLog.get_OldestEntryNumber() 049df27c 73bf24ed System.Diagnostics.EventLog.CompletionCallback(System.Object) 049df2c4 73bf0fe4 System.Diagnostics.EventLog.StaticCompletionCallback(System.Object,Boolean) 049df2f4 744fc3b8 System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context(System.Object,Boolean) 049df300 744fc373 System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context_f(System.Object) 049df304 7400027f System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,System.Threading.ContextCallback,System.Object) 049df31c 744fc477 System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(System.Object,Boolean) 049df4ac 74991b5c [GCFrame: 049df4ac]
如果它有帮助,我的应用程序只是检查写入事件日志的每个条目的事件ID,如果它匹配一个特定的一组ID,那么我记录它.崩溃很少发生安静,异常是System.ComponentModel.Win32异常,消息“访问被拒绝”.这听起来像是一个权限问题,但为什么它会在一段时间内正常工作,然后突然崩溃.
解决方法
如果我正确理解你的意思(如果你传递的stacktrace引导你得出一个线程池线程内的异常的结论),那么就把EventLogMonitor的代码包装在一个try / catch块中.
例:
void EventLogHandler(object sender,EventArgs args) { try { // Your original code. } catch (Exception ex) { // Log or Write "ex" to the console. Set a breakpoint,whatever. throw; } }
更新:在你的更新之后,它看起来好像异常确实没有从你的处理程序内部引发,甚至在EventLog类之前被调用.
您可以尝试使用AppDomain.UnhandledException
事件注册处理程序,并在其中进行日志记录/处理.请注意,这不允许您禁止或“更改”或包装异常,而只是将其记录到某处进行诊断.
如果你只想检查异常一次(或偶尔),你应该尝试在WinDBG中使用SOS扩展的!PrintException命令.
更新2:经过进一步调查,我发现异常气泡起来很奇怪.您的堆栈跟踪建议您使用.NET 3.5(或更早版本,但不是4.),并查看反射器中的EventLog类,您可以看到EventWrittenHandler的整个处理(包括似乎导致异常的前导码)是包裹在一个大的“try / catch(异常)/ catch”块中.滑稽.