在Windows窗体应用程序中捕获应用程序异常

27

有没有一种方法可以捕获代码中任何地方抛出的异常?我想以类似的方式捕获并处理异常,而不是为每个功能写try catch块。


1
这不是你想要做的事情,而是要在本地处理的基础上进行。请查看我的回答。 - Jodrell
4个回答

39

在Windows Forms应用程序中,当应用程序中的任何地方(在主线程或异步调用期间)抛出异常时,您可以通过在应用程序上注册ThreadException事件来捕获它。通过这种方式,您可以以同样的方式处理所有异常。

Application.ThreadException += new ThreadExceptionEventHandler(MyCommonExceptionHandlingMethod);

private static void MyCommonExceptionHandlingMethod(object sender, ThreadExceptionEventArgs t)
{
    //Exception handling...
}

9
以防能帮助到别人,请确保在运行应用程序之前(Application.Run(...))注册事件处理程序(Application.ThreadException += ...)。否则,它将无法正常工作(就像发生在我身上的那样)。 - Ramon Araujo
这回答了问题,但Brian Dishaw在他的答案中提供的链接非常全面,并涵盖了所有(如果不是所有)的用例。唯一无用的是返回带有错误消息提示框的方法。一个真正的生产应用程序将发送到事件日志,而不是在您的应用程序中弹出对话框。 - Entree

24

我认为这是在Win Form应用程序中最接近您所寻找的内容了。

http://msdn.microsoft.com/en-us/library/ms157905.aspx

// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);

// Set the unhandled exception mode to force all Windows Forms errors to go through
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

// Add the event handler for handling non-UI thread exceptions to the event. 
AppDomain.CurrentDomain.UnhandledException +=
    new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

如果不完成所有这些步骤,您可能会面临无法处理某些异常的风险。


这是我的主循环(我的应用程序以隐藏状态启动,并带有状态栏图标)。使用您的代码,我仍然需要在try/catch中包装new Form1();Application.Run();... - doekman

19
明显的解决方法是在执行链顶部添加一个异常处理程序。
[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    try
    {
        Application.Run(new YourTopLevelForm());
    }
    catch
    {
        //Some last resort handler unware of the context of the actual exception
    }
}

这将捕获在主GUI线程上发生的任何异常。如果您还想全局捕获发生在所有线程上的异常,可以订阅AppDomain.UnhandledException事件并在那里处理。

Application.ThreadException +=
    new ThreadExceptionEventHandler(MyCommonExceptionHandlingMethod)
private static void MyCommonExceptionHandlingMethod(
                                              object sender,
                                              ThreadExceptionEventArgs t)
{
    //Exception handling...
}

代码复制自Charith J的答案

现在给出建议...

这些选项只应作为最后一种选择使用,例如,如果您想将意外未捕获的异常从呈现给用户中抑制。尽可能早地捕获异常,当您了解异常上下文时。更好的方法是,您可以针对问题做些什么。

结构化异常处理可能看起来像是一个不必要的开销,你可以通过catch-all绕过它,但实际情况并非如此。而且,这个工作应该在编写代码时完成,当开发人员对逻辑有清晰的认识时。不要懒惰,留下这项工作供以后或交给更专业的开发人员去处理。

如果您已经知道并且做到了这一点,那我道歉。


4
@Downvoter,欢迎批评指正,我在这里学习。 - Jodrell

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接