Как: создать UnhandledException? - PullRequest
3 голосов
/ 19 мая 2010

Я использую этот код для перехвата UnhandledException приложения WinForm.

[STAThread]
static void Main(string[] args)
{
    // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new
      System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

    // 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(CurrentDomain_UnhandledException);

    try
    {
        Application.Run(new MainForm());
    } catch....

Там я попытаюсь перезапустить приложение.Теперь моя проблема - симулировать исключение, подобное этому.Я пытался, прежде чем пытаться (в основном): throw new NullReferenceException("test"); VS поймал его.

Пробовал также в коде MainForm с кнопкой:

    private void button1_Click(object sender, EventArgs ev)
    {         
        ThreadPool.QueueUserWorkItem(new WaitCallback(TestMe), null);
    }

    protected void TestMe(object state)
    {
        string s = state.ToString();
    }

не помогло, VS поймал его, даже в выпускеРежим.

  • Как, наконец, заставить приложение генерировать UnhandleldException?
  • Смогу ли я перезапустить приложение вCurrentDomain_UnhandledException?
  • Как сгенерировать ThreadException?

PS.

Если я запускаю внеVS универсальное окно Windows

Приложение MyApplication "обнаружило ошибку и должно быть закрыто ... blabla ... Отправить отчет / не отправлять.

Я хочу, однако, чтобы VS ввел этот метод (... Domain_Unhahdled ...)

РЕДАКТИРОВАТЬ: При перезапуске приложения можно отключить сообщение о сбое Windows , которое выглядит как: альтернативный текст http://byfiles.storage.msn.com/y1pOhWnAAXfMYtJH2VNa5iL0l1hjAqNHD2VmVnl8nN6L1oQC_xHkyHCJxhMc1ZLxLOH9ZXfZoo5zX8?PARTNER=WRITER?

Код:

static void CurrentDomain_UnhandledException(object sender, 
    UnhandledExceptionEventArgs e)
{
    // Since we can't prevent the app from terminating
    // log this to the event log.
    Logger.LogMessage(ERROR, errorMsg);
    Application.Restart();

Ответы [ 2 ]

6 голосов
/ 19 мая 2010

Я все еще не совсем уверен, что понимаю вопрос, но упомяну несколько вещей:

  • Application.ThreadException и Application.SetUnhandledExceptionMode применяются только к потокам Windows Forms.Произвольные потоки ThreadPool на самом деле не являются потоками Windows Forms, даже в приложении Winforms, поэтому эти две строки кода неэффективны.

  • Регистрация события с помощью AppDomain.CurrentDomain.UnhandledException будет исключения ловушек, возникающие в потоках ThreadPool.

  • Однако , событие UnhandledException не может фактически обрабатывать исключение.К тому времени уже слишком поздно, чтобы остановить завершение процесса, что всегда будет происходить, если в фоновом потоке возникает исключение (если вы не включили устаревшее поведение .NET 1.1, но ... не делаете.) Это событиедействительно хорош только для регистрации или очистки.

Я сам проверил это, используя тестовый код, похожий на ваш, и убедился, что код внутри исключения «обработчик» действительно выполняется.Но приложение все равно будет зависать, и вы не сможете его остановить.

Обновление: Я собираюсь сделать еще одну попытку, и все.

Если ваша цель - постоянно запускать приложение без присмотра, у вас есть три варианта:

  1. Правильно обрабатывайте исключения. Это безусловно, , лучшее и, вероятно, единственно правильное решение.Перехват AppDomain.UnhandledException - это , а не , обрабатывающий исключение.К тому времени, когда элемент управления войдет в этот обработчик событий, в вашем приложении уже произошел сбой.Вы больше не можете его сохранить.

    Необработанное исключение, выходящее из фонового потока, является катастрофической ошибкой в ​​вашем коде, которую необходимо исправить.Необработанное исключение, выходящее из фонового потока, является катастрофической ошибкой в ​​вашем коде, которую вам нужно исправить.Необработанное исключение, выходящее из фонового потока, является катастрофической ошибкой в ​​вашем коде, которую вам необходимо исправить. Пожалуйста, больше никаких комментариев к эффекту "Мне все равно" - вам нужно начать заботливый.

  2. Попросите Windows вежливо перезапустить приложение для вас. В отличие от попытки перезапуска из обработчика сбоя, который невероятноплохая идея по причинам, слишком многочисленным для полного перечисления (повреждение данных, бесконечные циклы перезапуска, утечки ресурсов, нестабильность ОС и т. д.), регистрация 1064 * для перезапуска фактически позволяет этому происходить полууправляемым образом.Как я упоминал в комментариях, просто взаимодействовать с этим API в .NET.Вы регистрируетесь для этого, как только приложение запускается, а не когда происходит сбой, и ваше приложение находится в ненадежном состоянии.

  3. Создайте службу супервизора, которая будет наблюдать за вашим приложением и перезапускать его в случае сбоя.,Это по-прежнему плохо по многим причинам, обсуждавшимся в предыдущих двух пунктах, но у вас, по крайней мере, есть некоторый шанс на некоторый уровень стабильности.

    Вы можете получить достаточно надежное указание на сбой приложения, используяс именем mutex, ожидая этого в вашем супервизоре и следя за состоянием WAIT_ABANDONED (AbandonedMutexException в .NET).Заброшенное состояние возникает только тогда, когда процесс, который владеет мьютексом, завершается без его освобождения, то есть имеет необработанное исключение.И с немного большим количеством хакерских атак вы также можете обнаружить и закрыть окно сбоя.

Это ваши варианты.Я настоятельно рекомендую вам обрабатывать исключения в фоновых потоках, потому что необработанное исключение, выходящее из фонового потока, является катастрофической ошибкой в ​​вашем коде, которую необходимо исправить. Если это происходит из внешнего компонента, и вы можете 'Если вы не поймете это, то катастрофическая ошибка в этом компоненте, и вам следует рассмотреть возможность сообщить об этом автору или использовать другой компонент.

Простое требование, гласящее, что «это приложение должно работать постоянно и должно полностью игнорировать фатальные сбои», не делает такой сценарий возможным, если приложение недостаточно стабильно, чтобы фактически продолжать работать. Авария - это крушение. Вы не разрабатываете машину, чтобы просто перезапустить себя немедленно, если двигатель внезапно заглох. Лучшее, что вы можете сделать, - это попросить доверенного оператора, будь то оператор, операционная система или какое-либо контролирующее программное обеспечение, перезапустить приложение от его имени.

Вариации этого вопроса, кажется, возникают так часто - в основном: «Мое приложение никогда не должно падать, или, если оно происходит, оно должно быть невидимым. Я хочу съесть каждое необработанное исключение и сделать вид, что этого не произошло». Это не только невозможно, но и противоречит практически каждому принципу хорошего дизайна (особенно принципу «быстро провалиться», который, безусловно, может быть истолкован заново, но никогда не должен игнорироваться полностью).

Это все, что я могу сказать. Если вы не хотите принимать что-либо из этого, тогда удачи в поиске приемлемой альтернативы.

0 голосов
/ 19 мая 2010

Visual Studio может быть настроен на прерывание исключений, но если вы продолжите шагать по коду, он все равно должен следовать по выбранному пути. Вам также следует попробовать запустить приложение за пределами VS.

Перезапуск приложения после необработанного исключения - плохая идея, потому что вы (по определению) находитесь в неизвестном состоянии. Перезапуск, если это возможно, может поставить вас в бесконечный цикл перезапуска, если условие исключения никогда не изменяется. Вместо этого попробуйте зарегистрировать информацию об исключении на веб-сервере, чтобы вы могли расследовать и устранять сбои. Обязательно получите разрешение пользователя, прежде чем загружать данные о сбое.

...