捕获Main()方法中的exception

考虑下面这个简单的应用程序:一个由VS中的“新C#窗口应用程序”序列创build的窗体,以下面的方式进行修改:

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,那么,正如我所期望的那样,我看到一个消息框,表示exception被捕获,应用程序退出。

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

显然,这与exception从Application.Run被调用的另一个线程抛出有关。 但是问题依然存在 – 为什么行为会根据应用程序是从IDE还是从命令行运行而有所不同? 确保应用程序中没有任何exception仍未处理的最佳做法是什么?

通常,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事件中的异常会被吞下而不会诊断。 强制任何CPU模式,以避免陷阱。

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

不知道为什么行为与附加调试器不同,但是。