Подтвердить что ты не робот

Обработка необработанных исключений

Я хотел установить некоторый обработчик для всех неожиданных исключений, которые, возможно, не попали в мой код. В Program.Main() я использовал следующий код:

AppDomain.CurrentDomain.UnhandledException
    += new UnhandledExceptionEventHandler(ErrorHandler.HandleException);

Но это не сработало, как я ожидал. Когда я запустил приложение в режиме отладки и выбросил исключение, он вызвал обработчик, но впоследствии помощник исключения в Visual Studio появился, как если бы исключение произошло без какой-либо обработки. Я пробовал Application.Exit() внутри обработчика, но он не работал.

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

4b9b3361

Ответ 1

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

Ответ 2

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

using System;

static class Program
{
  [STAThread]
  static void Main(string[] argv)
  {
    try
    {
      AppDomain.CurrentDomain.UnhandledException += (sender,e)
      => FatalExceptionObject(e.ExceptionObject);

      Application.ThreadException += (sender,e)
      => FatalExceptionHandler.Handle(e.Exception);

      // whatever you need/want here

      Application.Run(new MainWindow());
    }
    catch (Exception huh)
    {
      FatalExceptionHandler.Handle(huh);
    }
  }

  static void FatalExceptionObject(object exceptionObject) {
    var huh = exceptionObject as Exception;
    if (huh == null) {
      huh = new NotSupportedException(
        "Unhandled exception doesn't derive from System.Exception: "
         + exceptionObject.ToString()
      );
    }
    FatalExceptionHandler.Handle(huh);
  }
}

Возможно, это то, что вам тоже полезно? Этот основной код маршрутизирует все три способа обнаружения неожиданных исключений верхнего уровня посредством одного вызова метода. Теперь вам нужен только статический класс FatalExceptionHandler, который включает обработку исключений верхнего уровня в своем методе Handle.

И действительно, любой разработчик приложений знает, что на самом деле есть только две вещи:

  • Показывать/регистрировать исключение, которое вы считаете нужным
  • Убедитесь, что вы завершаете/завершаете процесс приложения.

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

Мертвые программы не говорят лжи...; -)

Ответ 3

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

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

Ответ 4

Возможно, вы ищете Environment.Exit(int errorcode)

Ответ 5

Это поведение по дизайну.

Но есть обход.

Либо вы вызываете Process.GetCurrentProcess().Kill(); внутри обработчика, либо просто не позволяете обработчику завершить работу.

Посмотрите пример:

class Program
{
    void Run()
    {
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        Console.WriteLine("Press enter to exit.");

        do
        {
            (new Thread(delegate()
            {
                throw new ArgumentException("ha-ha");
            })).Start();

        } while (Console.ReadLine().Trim().ToLowerInvariant() == "x");


        Console.WriteLine("last good-bye");
    }

    int r = 0;

    void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Interlocked.Increment(ref r);
        Console.WriteLine("handled. {0}", r);
        Console.WriteLine("Terminating " + e.IsTerminating.ToString());

        Thread.CurrentThread.IsBackground = true;
        Thread.CurrentThread.Name = "Dead thread";            

        while (true)
            Thread.Sleep(TimeSpan.FromHours(1));
        //Process.GetCurrentProcess().Kill();
    }

    static void Main(string[] args)
    {
        Console.WriteLine("...");
        (new Program()).Run();
    }
}

Это не должно быть стандартным приемником для исключений.

Но это нужно сделать, чтобы излагать исключения изящно.