Почему исключение 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) Это зависит от структуры вашего приложения. Например, если ваш интерфейс уведомления об ошибках каким-то образом привязан к основной форме (например, вам нужно вызвать поток пользовательского интерфейса из рабочего потока), тогда было бы глупо отображать пользовательский интерфейс в кодовом блоке вне кода, который запускает сообщение петля. Однако, если ваш пример кода является однопоточным, это будет нормально.