在Main()方法中捕获异常

时间:2010-04-27 11:27:44

标签: c# .net windows visual-studio winforms

考虑以下简单应用程序:由VS中的“新C#windows应用程序”序列创建的窗口表单,该表单以下列方式修改:

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");

}

如果我在IDE中按F5,那么,正如我所料,我看到一个消息框,说明异常被捕获并且应用程序退出。

如果我去Debug(或Release)/ bin并启动可执行文件,我会看到标准的“Unhandled exception”窗口,这意味着我的异常处理程序不起作用。

显然,这与从调用Application.Run的其他线程抛出的异常有关。但问题仍然存在 - 为什么行为会因应用程序是从IDE运行还是从命令行运行而有所不同? 确保应用程序中没有未处理异常的最佳做法是什么?

2 个答案:

答案 0 :(得分:10)

通常,Application.ThreadException将处理Load事件中的异常。您将获得提供退出和继续选项的ThreadExceptionDialog。

但是在连接调试器时却没有。在这种情况下,有意禁用显示对话框的消息循环中的catch子句。这是必要的,因为如果在调试程序时弹出该对话框,则很难排除异常。这个捕获器不再处于活动状态,Main()方法中的catch子句现在可以查看异常。

您可以通过在Main()方法中使用Application.SetUnhandledExceptionMode()使其保持一致。您不应该,如果您这样做, 很难调试。如果要为UI线程自定义异常处理,则应注册自己的Application.ThreadException处理程序:

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

在工作线程中捕获未处理的异常需要AppDomain.UnhandledException处理程序。它们无法恢复。

还要注意64位Windows中的错误,在连接调试器时,如果没有诊断,则会吞下Load事件中的异常。强制AnyCPU模式以避免该陷阱。

答案 1 :(得分:5)

除了捕获Main方法中引发的任何异常之外,您还必须处理AppDomain.CurrentDomain.UnhandledExceptionApplication.ThreadException

不确定无论是否附加调试器,行为都会有所不同。