处理未处理的异常问题

时间:2009-01-02 09:42:49

标签: c# exception

我想为我可能没有在代码中捕获的所有意外异常设置一些处理程序。在Program.Main()中,我使用了以下代码:

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

但它没有像我预期的那样奏效。当我在调试模式下启动应用程序并抛出异常时,它确实调用了处理程序,但之后Visual Studio中的异常帮助程序弹出,好像发生了异常而没有任何处理。我在处理程序中尝试了Application.Exit(),但它也没有用。

我想要实现的是异常是用我的处理程序处理的,然后应用程序很好地关闭。有没有其他方法可以做到这一点,还是我以错误的方式使用上面的代码?

5 个答案:

答案 0 :(得分:34)

通常我会使用类似的东西来尝试捕获所有意外的顶级异常。

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方法中的顶级异常处理。

实际上,任何应用程序开发人员都知道实际上只有两件事要做:

  1. 显示/记录您认为合适的异常
  2. 确保退出/终止申请流程
  3. 如果您认为第二项是奇怪的,请记住,我们只是为了非常特殊的情况而首先要这么做。这些东西可能是需要更改应用程序才能准确解决的错误。任何其他异常处理 - 功能类型 - 应该在实际程序代码中降低,捕获特定类型的异常,这是有意义的,并以有意义的方式处理它们。还有其他任何东西应该冒泡到你的FatalExceptionHandler以使自己知道,并阻止可能残缺的程序在腐败状态下工作

    死亡程序不会说谎......; - )

答案 1 :(得分:29)

这是因为您在调试模式下通过Visual Studio运行它。如果您在其他地方发布并安装应用程序,则只会处理您的全局异常处理程序。

答案 2 :(得分:8)

请注意,未处理的异常仍然非常致命;你只能真正用它来记录,或者可能是一些仓促的关闭。这个和Application.ThreadException都不能用作错误的全局接收器。

更好的方法是添加适当的处理 - 例如,围绕整个Main()逻辑。请注意,即使也无法捕获一些例外情况,例如表单加载期间的错误(特别令人讨厌 - 您可以使用附加的调试器来捕获它们,但不是没有。)

答案 3 :(得分:2)

也许您正在寻找的是Environment.Exit(int errorcode)

答案 4 :(得分:0)

这种行为是设计的。

是一种解决方法。

要么在处理程序中调用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();
    }
}

这肯定不是异常的默认接收器。

但是应该这样做才能优雅地报告异常。