C # Catching исключение, которое происходит на ThreadPool - PullRequest
10 голосов
/ 12 января 2012

Я расследую некоторые сбои в моем приложении, вызванные исключением Win32, и я сузил его, чтобы он происходил в пуле потоков, который обрабатывает обработчик событий EventLog.EntryWrittenEventHandler в моем приложении.Я настроил это так:

// Create the event log monitor
eventLog.Log = "Application";
eventLog.EnableRaisingEvents = true;
eventLog.EntryWritten += new EntryWrittenEventHandler(EventLogMonitor);

EventLogMonitor - это обработчик для моего события.Мне интересно, есть ли у кого-нибудь какие-либо идеи относительно того, где я мог бы выяснить, что является причиной этого исключения.Похоже, что для прослушивания событий настраивается ThreadPoolWaitOrTimerCallback, на котором не было бы никакого моего кода, и, если происходит исключение, я просто не могу понять, как справиться с этой проблемой.Любая помощь действительно приветствуется !!

Вот вывод! Clrstack в WinDBG:

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] 

Если это помогает, мое приложение просто проверяет идентификатор события каждой записи, записанной вжурнал событий, и если он соответствует одному из определенного набора идентификаторов, я регистрирую его.Сбои происходят тихо, редко, и исключением является исключение System.ComponentModel.Win32 с сообщением «Доступ запрещен».Звучит так, как будто это может быть проблема с разрешениями, но почему она будет работать нормально в течение определенного периода времени, а затем внезапно завершится с этим.

Ответы [ 4 ]

5 голосов
/ 12 января 2012

Если я вас правильно понимаю (это поможет, если вы передадите трассировку стека, которая приведет вас к выводу, что исключение происходит внутри потока пула потоков), тогда просто оберните ваш код 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;
   }
}

ОБНОВЛЕНИЕ : после вашего обновления это выглядит так, как будто исключение действительно не вызывается изнутри вашего обработчика, но даже до того, как оно даже вызывается из EventLogclass.

Вы можете попробовать зарегистрировать обработчик с событием AppDomain.UnhandledException и выполнить там регистрацию / обработку.Обратите внимание, что это не позволит вам подавить, «изменить» или обернуть исключение, а просто зарегистрировать его где-то в диагностических целях.

Если вы просто хотите проверить исключение один раз (или в некоторых случаях), выследует попробовать использовать команду !PrintException SOS-расширения в WinDBG.

ОБНОВЛЕНИЕ 2 : после дальнейших исследований я нахожу довольно странным, что исключение запутывает все.Ваша трассировка стека предполагает, что вы используете .NET 3.5 (или более раннюю, но не 4.) и, глядя на класс EventLog в Reflector, вы можете видеть, что вся обработка EventWrittenHandler, включая код преамбулы, кажется, вызывает исключение., упакован в один большой блок "try / catch (Exception) / catch".Забавно.

1 голос
/ 21 января 2012

Подпишитесь на Application.ThreadException в вашем Program.cs следующим образом, чтобы иметь возможность перехватывать исключения, которых нет в главном потоке.

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);
    }
0 голосов
/ 21 января 2012

Не уверен, что это за приложение, поэтому в общем случае, если вам не повезло, попробуйте подключиться к домену приложений, в котором выполняется код.Если у вас нет нескольких доменов, вы можете попробовать:

AppDomain.CurrentDomain.FirstChanceException += Handler

или

AppDomain.CurrentDomain.UnhandledException += Handler

0 голосов
/ 17 января 2012
  1. Если можете, используйте Задачи в System.Threading.Tasks.
  2. Попробуйте, где действие выполняет то, что вы хотите.

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