Исключение С# Catching, которое происходит на ThreadPool
Я изучаю некоторые сбои в моем приложении, вызванные исключением Win32, и я сузил его, что он должен произойти в threadpool, который заботится о обработчике событий EventLog.EntryWrittenEventHandler
в моем приложении. Я установил это следующим образом:
// Create the event log monitor
eventLog.Log = "Application";
eventLog.EnableRaisingEvents = true;
eventLog.EntryWritten += new EntryWrittenEventHandler(EventLogMonitor);
EventLogMonitor
является обработчиком моего события. Мне интересно, есть ли у кого-нибудь какие-либо идеи относительно того, где я могу узнать, что вызывает это исключение. Кажется, что для прослушивания событий создается a 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". Похоже, что это может быть проблема с разрешениями, но почему она будет работать нормально в течение определенного периода, а затем внезапно сработает с этим.
Ответы
Ответ 1
Если я правильно вас понимаю (это поможет, если вы передадите стек, который приведет вас к выводу, что исключение происходит внутри потока 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
и сделать там свою регистрацию/обработку. Обратите внимание, что это не позволит вам подавить или "изменить" или обернуть исключение, а просто зарегистрировать его где-нибудь в диагностических целях.
Если вы просто хотите проверять исключение один раз (или иногда), вы должны попробовать использовать команду SOS-extension !PrintException
в WinDBG.
ОБНОВЛЕНИЕ 2: после дальнейших исследований мне кажется довольно странным, что исключение всплывает. Ваша stacktrace предполагает, что вы используете .NET 3.5 (или ранее, но не 4.) и глядя на класс EventLog в Reflector, вы можете видеть, что вся обработка EventWrittenHandler
, включая код преамбулы, который, кажется, вызывает исключение, завернут в один большой блок try/catch (Exception)/catch. Забавно.
Ответ 2
Подпишитесь на 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);
}
Ответ 3
- Если вы можете, используйте Задачи в
System.Threading.Tasks
.
-
Попробуйте, где действие выполняет то, что вы хотите.
ThreadPool.QueueUserWorkItem(state =>
{
try
{
action();
}
catch (Exception ex)
{
OnException(ex);
}
});
Ответ 4
Не уверен, какое приложение это, поэтому в общем случае, если вам не повезло, попробуйте подключиться к AppDomain, в котором работает код. Если у вас нет нескольких доменов, вы можете попробовать:
AppDomain.CurrentDomain.FirstChanceException += Handler
или
AppDomain.CurrentDomain.UnhandledException += Handler