Поймать исключение в методе Main () - PullRequest
6 голосов
/ 27 апреля 2010

Рассмотрим следующее простое приложение: форму окна, созданную последовательностью «новое приложение C # windows» в VS, которая была изменена следующим образом:

public static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    try
    {
        Application.Run(new Form1());
    }
    catch (Exception ex)
    {
        MessageBox.Show("An unexpected exception was caught.");
    }

}

Form1.cs содержит следующие модификации:

private void Form1_Load(object sender, EventArgs e)
{
    throw new Exception("Error");

}

Если я нажимаю F5 в IDE, то, как и ожидалось, я вижу окно с сообщением о том, что возникла исключительная ситуация, и приложение закрывается.

Если я захожу в Debug (или Release) / bin и запускаю исполняемый файл, я вижу стандартное окно «Необработанное исключение», означающее, что мой обработчик исключений не работает.

Очевидно, что это связано с тем, что исключение выдается из другого потока, из которого вызывается Application.Run. Но остается вопрос - почему поведение отличается в зависимости от того, было ли приложение запущено из IDE или из командной строки? Какова наилучшая практика, позволяющая гарантировать, что никакие исключения не останутся необработанными в приложении?

Ответы [ 2 ]

10 голосов
/ 27 апреля 2010

Обычно Application.ThreadException обрабатывает исключение в событии Load. Вы получите ThreadExceptionDialog, который предлагает опции Quit и Continue.

Но не тогда, когда отладчик подключен. В этом случае предложение catch в цикле сообщений, отображающем диалоговое окно, намеренно отключено. Это необходимо, потому что было бы очень трудно выявлять исключения, если этот диалог появляется при отладке программы. Какой этот перехватчик больше не активен, ваше предложение catch в методе Main () теперь получает шанс на исключение.

Вы можете сделать это согласованно, используя Application.SetUnhandledExceptionMode () в методе Main (). Вы не должны этого делать, исключения, действительно , трудно отлаживать, если вы сделаете это. Если вы хотите настроить обработку исключений для потока пользовательского интерфейса, вам следует зарегистрировать собственный обработчик Application.ThreadException:

  if (!System.Diagnostics.Debugger.IsAttached)
    Application.ThreadException += myThreadException;

Для захвата необработанных исключений в рабочих потоках требуется обработчик AppDomain.UnhandledException. Они не подлежат восстановлению.

Также остерегайтесь ошибки в 64-битной Windows, исключения в событии Load проглатываются без диагностики, когда подключен отладчик. Включите режим AnyCPU, чтобы избежать этой ловушки.

5 голосов
/ 27 апреля 2010

В дополнение к отлову любых исключений, возникающих в методе Main, вы также должны обрабатывать AppDomain.CurrentDomain.UnhandledException и Application.ThreadException.

Не уверен, почему поведение отличается с отладчиком и без него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...