Недавно я столкнулся с поведением, которое я никогда раньше не видел. Я не могу понять, что происходит, скорее всего, из-за отсутствия фундаментальных знаний в отношении внутренней обработки Exception Handling - или, может быть, я просто пропущу что-то очевидное.
Недавно я добавил обработку исключений в приложение как своего рода резерв в случае необработанных исключений. Я в основном обрабатываю ThreadException и UnhandledException, как показано ниже:
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new ThreadExceptionEventHandler(ExceptionHandler.OnUIThreadException);
// Set the unhandled exception mode to force all Windows Forms errors to go through
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(ExceptionHandler.OnUnhandledException);
// Runs the application.
Application.Run(new ErrorHandlerForm());
Некоторый другой фрагмент кода, который у меня был в приложении, уже улавливал исключения - и поскольку у меня не было обработки исключений, я просто перестраивал исключение, чтобы убедиться, что он не проглотил:
//code in some method of the Program
try
{
foo.SomeFooCall();
}
catch(Exception ex)
{
logger.Log(ex.Message);
// I don't swallow!
throw;
}
Как только у меня была обработка исключений на месте (которая также регистрируется), я должен был удалить этот блок try catch выше, но я забыл сделать это, и я испытываю странное поведение, которое является предметом этого вопроса.
Когда и исключение выбрасывается где-то внутри вызова foo, он, очевидно, попадает в код выше, записывается и снова бросается. На этом этапе ExceptionHandling запускается, происходит ли какое-то ведение журнала и уведомление (простое сообщение), а затем идет Application.Exit()
. Что будет дальше, так это то, что приложение вернется к тому же throw
, что приведет к обработке ошибок с теми же результатами, и это будет продолжаться несколько раз, пока оно не сработает, предположительно, потому что трассировка стека заполнена или она каким-то образом обнаруживает бесконечный цикл.
РЕДАКТОР: Вышеприведенный режим находится в режиме отладки - если я его запустил, он будет обрабатывать исключение один раз (показать сообщение, журнал и т.д.), тогда он просто сработает (я предполагаю, что переполнение стека).
Я ожидаю, что ответ на этот вопрос может быть тривиальным (или я могу пропустить что-то очевидное), но любые указатели/объяснения будут высоко оценены.
EDIT: Методы обработчиков исключений принимают оба метода вызова к методу OnException, который выглядит примерно так:
private void OnUIThreadException(object sender, ThreadExceptionEventArgs e)
{
OnException(e.Exception);
}
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
OnException((Exception)e.ExceptionObject);
}
private void OnException(Exception exception)
{
MessageBox.Show("Fatal Exception: " + exception.Message);
logger.Log(LoggingLevel.FATAL, "myLousyApp", exception.Message);
Application.Exit();
}
Я на самом деле делаю smt больше, чем просто, - например, спрашивать у пользователя, хочет ли он перезапустить приложение, и если он перезапустил его с идентификатором процесса как cmd arg, так что когда он перезагрузится, он будет ждать, пока старый процесс exit (он защищен от экземпляров дубликатов через мьютекс). Но для этого вопроса это не имеет значения, так как я не перезапускаю приложение, когда испытываю описанное поведение.
EDIT: Я создал еще одно простое приложение для воспроизведения этих условий - у меня есть простой компонент, который генерирует исключения (я выбрасываю произвольное количество исключений в цикле), но во всех моих тестах Application.Exit приложение просто прекращает работу, и я не могу воспроизвести его. Озадаченный тем, что я должен искать!