为什么C#异常处理机制无法捕获Win32异常

14

我有一个WinForms应用程序。WinForms从Program.cs开始,其中我们定义了main()。我将此代码放在try-catch块中。

 [STAThread]
    static void Main()
    {
        try
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new frmSplash());
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            if (ex.InnerException != null)
            {
                MessageBox.Show(ex.InnerException.ToString());
            }
        }
    }

每当出现win32异常时,此机制将失败,抛出未处理的异常消息并导致应用程序崩溃。
我有两个问题与此代码相关:

1)为什么不捕获win32异常。

2)在最高级别捕获异常是一种好的实践吗。


1
哇,我从未想过这个问题,好问题和好答案 :) - leppie
请也对第二个问题发表评论。 - Rohit Raghuvansi
也许你可以把它作为第二个Stack Overflow问题;-) - Mac
6个回答

17

4
默认情况下,.Net 2.0不需要这个。所有非CLS异常都被包装为RuntimeWrappedException。参见http://msdn.microsoft.com/en-us/library/ms404228.aspx。 - softveda
Win32Exception < ExternalException < SystemException < ExceptionWin32Exception < ExternalException < SystemException < Exception - Tommy Carlier

3
Application.Run的执行并不会抛出错误。这种情况可能在另一个线程(或至少是异步地)发生。
友好地通知用户应用程序已经失败,然后再完全消失是个好主意,但仅仅捕获异常然后继续执行并不是明智之举。

3
虽然我不清楚为什么您的捕获块不起作用,但建议尝试使用Application ThreadException Event。这可以捕获应用程序线程中的任何错误。在调用Application.Run之前添加事件处理程序。
对于第二个问题的答案绝对是肯定的。我开发和维护一个企业WinForms应用程序,它与后台线程上的Web服务进行通信。如果任何Web服务调用崩溃,请处理应用程序线程异常(以及AppDomain UnhandledException)事件,并记录并弹出一个错误,使业务用户可以报告并允许他们在不崩溃应用程序的情况下继续操作。

2
尝试在应用程序启动前(Application.Run)订阅以下事件: 然后,您可以摆脱try catch块。
我认为在最高级别捕获异常是不好的实践,但您无法避免!在开发期间(Debug),那些异常不应该被捕获,应用程序应该做最糟糕的事情(崩溃?)。在生产环境(Release)中,即使出现未处理的异常,您也希望您的应用程序尽可能地降级。这是我发现的DEBUG预处理器变量的少数用途之一。

这里有两个答案。你会选择哪一个(支持或反对)? - Mac

0

你可能需要捕获 Win32Exception(或 ExternalException)

http://msdn.microsoft.com/en-us/library/system.componentmodel.win32exception.aspx

我记得Win32Exception继承自ExternalException,但ExternalException并不继承自Exception,所以你的代码无法捕获它。

编辑:请参考其他答案,了解为什么这是错误的!

编辑2:至于第二部分,正如AnthonyWJones所述,让用户知道问题导致应用程序关闭是好习惯,但我建议使用简单明了的英语陈述向用户说明,并将异常堆栈记录到日志文件中供您自己使用。


1
这两个都是从Exception派生而来的,因此表面上看问题中的catch应该可以工作。为什么它不起作用,请参见我的答案。 - AnthonyWJones

0

1) 应该捕获Win32异常。也许异常是从后台线程或GC线程抛出的?

2) 这取决于您的应用程序结构。例如,如果您的错误通知UI与主窗体某种方式绑定(例如,您需要从工作线程调用UI线程),那么在运行消息循环的代码块之外显示UI将是愚蠢的。但是,如果您的代码示例是单线程的,则可以这样做。


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