2012-01-12 4 views
10

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

// 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 с сообщением «Access denied». Похоже, что это может быть проблема с разрешениями, но почему она работает нормально на определенный период, а затем внезапно падает с этим.

+0

Какие исключения это? –

+0

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

+0

Возможно ли, что вы пытаетесь создать свой собственный, никогда ранее используемый источник событий, и что он падает только тогда? –

ответ

5

Если я правильно вас понимаю (это поможет, если вы передадите стек, который приведет вас к выводу, что исключение происходит внутри потока threadpool), а затем просто заверните свой код 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 и выполнить регистрацию/обработку. Обратите внимание, что это не позволит вам подавить или «изменить» или обернуть исключение, а просто зарегистрировать его где-нибудь в диагностических целях.

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

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

+0

Я добавил выход clrstack к моему вопросу. Я действительно пробовал то, что вы предлагаете Christian.K, и мое приложение все еще разбилось, не пытаясь попробовать/поймать. Исключение происходит на некоторых Threadpool, которые .NET должен настроить для прослушивания записей записи из журнала событий, а исключения не распространяются на потоки, поэтому я не думаю, что это сработает. Спасибо за предложение! – DukeOfMarmalade

+0

Спасибо за помощь по этой проблеме Christian.K, я до сих пор не понял этого, должен был передать вопрос Microsoft, ваши предложения помогли много разобраться с проблемой! – DukeOfMarmalade

+0

Жаль, что мы не смогли понять это полностью. Я несколько раз пересматривал эту проблему, несколько раз, но не придумывал никаких новых идей (на самом деле это не очень много говорит :-). –

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

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

Я не думаю, что это сработает, когда вы подписываетесь на обработчик событий EventLogEntryWritten, отдельный ThreadPool, похоже, начинает отслеживать записи, записанные в журнал событий, именно на этом ThreadPool возникает исключение. – DukeOfMarmalade

1

Подписаться на 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); 
    } 
+2

+1 для ThreadException! –

0

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

AppDomain.CurrentDomain.FirstChanceException += Handler

или

AppDomain.CurrentDomain.UnhandledException += Handler

Смежные вопросы