考虑下面这个简单的应用程序:一个由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.UnhandledException
和Application.ThreadException
。
不知道为什么行为与附加调试器不同,但是。