Почему исключение win32 не попадает в механизм обработки исключений С#
У меня есть winforms application.Winforms начинаются с Program.cs, где у нас есть main(). Я поставил этот код в блок try-catch.
[STAThread]
static void Main()
{
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmSplash());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
if (ex.InnerException != null)
{
MessageBox.Show(ex.InnerException.ToString());
}
}
}
Всякий раз, когда есть исключение win32, этот механизм выходит из строя, и отправляется необработанное сообщение об исключении, а приложение вылетает.
У меня есть 2 вопроса относительно этого кода:
1) Почему исключения win32 не попадают.
2) Является ли хорошей практикой ловить исключения на самом высоком уровне.
Ответы
Ответ 1
EDIT: как указано Pratik, следующий ответ относится только к .NET 1.0 и .NET 1.1. Начиная с .NET 2.0 исключение, отличное от CLS, должно быть обнаружено как RuntimeWrappedException.
Поскольку исключения Win32 не относятся к классу .NET Exception. Попробуйте:
try {
} catch (Exception ex) {
// .NET exception
} catch {
// native exception
}
См. Дополнительные сведения об исключении CLSCompliant для общих обработчиков.
Ответ 2
Выполнение Application.Run не вызывает ошибку. Это происходит в другом потоке (или, по крайней мере, асинхронно).
Его хорошая идея - сообщить пользователю дружеским образом, что приложение потерпело неудачу, прежде чем оно полностью исчезнет, однако его не рекомендуется просто ловить, а затем продолжить.
Ответ 3
Пока я не знаю, почему ваш блок catch не работает, попробуйте использовать Application ThreadException Event. Это должно ловить любую ошибку в потоках приложений. Добавьте обработчик событий перед вызовом Application.Run.
Для вашего второго ответа определенно да. Я разрабатываю и поддерживаю приложение winforms предприятия, которое разговаривает с бэкэндом веб-службы по фоновым потокам. Если какой-либо сбой при вызове webservice обрабатывает событие приложения threadexception (а также appdomain unhandledexception), регистрирует и выдает сообщение об ошибке, которую могут сообщить бизнес-пользователи, и разрешить им продолжить работу без сбоев приложения.
Ответ 4
Попробуйте подписаться на эти события перед запуском приложения (Application.Run
):
Затем вы можете избавиться от своего блока try catch
.
Я думаю, что это плохая практика, чтобы ловить исключения на самом высоком уровне, но вы не можете этого избежать! Во время разработки (Debug) эти исключения не должны быть пойманы, и приложение должно делать самую неприятную вещь (crash?). В производстве (Release) вы захотите, чтобы ваше приложение деградировало как можно лучше даже в случае необработанных исключений. Это одно из немногих применений, которое я нашел для переменной DEBUG
препроцессора.
Ответ 5
Возможно, вам придется поймать как Win32Exception (или ExternalException)
http://msdn.microsoft.com/en-us/library/system.componentmodel.win32exception.aspx
Кажется, я помню, что Win32Exception наследует от ExternalException, но ExternalException не наследует от Exception, поэтому вы не поймаете ваш код.
Изменить: Другие ответы, почему это неправильно!
Изменить 2: Что касается второй части, как указано AnthonyWJones. Хорошие манеры позволяют пользователю узнать, что проблема вызвала закрытие приложения, однако я бы рекомендовал использовать простой английский оператора и регистрации стека исключений в файл журнала для вашего собственного использования.
Ответ 6
1) Следует исключить исключения Win32. Может быть, исключение выбрасывается из фонового потока или потока GC?
2) Это зависит от структуры вашего приложения. Например, если ваш интерфейс уведомления об ошибках каким-то образом привязан к основной форме (например, вам нужно вызвать поток пользовательского интерфейса из рабочего потока), тогда было бы глупо отображать пользовательский интерфейс в кодовом блоке вне кода, который запускает сообщение петля. Однако, если ваш пример кода является однопоточным, это будет нормально.