C#捕获ThreadPool上发生的异常

时间:2012-01-12 14:33:54

标签: c# exception threadpool

我正在研究由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异常,消息“访问被拒绝”。听起来这可能是一个权限问题,但为什么它会在一段时间内正常工作然后突然崩溃。

4 个答案:

答案 0 :(得分:5)

如果我理解正确(如果你传递的栈跟踪会导致你在线程池线程中发生异常,那将会有所帮助),然后将你的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;
   }
}

UPDATE :更新后,看起来好像是从处理程序内部引发了异常,但是在它甚至在EventLog类中调用之前。

您可以尝试使用AppDomain.UnhandledException事件注册处理程序,并在那里进行日志记录/处理。请注意,这不允许您抑制或“更改”或包装异常,而只是将其记录在某处以进行诊断。

如果您只想检查一次(或偶尔)异常,则应尝试在WinDBG中使用SOS-extension的!PrintException命令。

更新2 :经过进一步调查后,我觉得奇怪的是异常会冒泡。您的堆栈跟踪建议您使用.NET 3.5(或更早版本,但不是4.)并查看Reflector中的EventLog类,您可以看到EventWrittenHandler的整个处理,包括似乎导致的前导代码异常,包含在一个大的“try / catch(异常)/ catch”块中。有趣的。

答案 1 :(得分:1)

在Program.cs中订阅Application.ThreadException,如下所示,以便能够捕获不在主线程中的异常。

static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.ThreadException += Application_ThreadException;
        try
        {
            Application.Run(new MainForm());
        }
        catch (Exception e)
        {
            HandleException(e);
        }
    }

    static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
    {
        HandleException(e.Exception);
    }

答案 2 :(得分:0)

  1. 如果可以,请使用System.Threading.Tasks中的任务。
  2. 尝试执行您想要的操作。

    ThreadPool.QueueUserWorkItem(state =>
    {
        try
        {
            action();
        }
        catch (Exception ex)
        {
            OnException(ex);
        }
    });
    

答案 3 :(得分:0)

不确定这是什么类型的应用程序,因此在一般情况下,如果您没有运气,请尝试连接到运行代码的AppDomain。如果您没有多个域,可以尝试:

AppDomain.CurrentDomain.FirstChanceException += Handler

AppDomain.CurrentDomain.UnhandledException += Handler