捕获块未捕获异常

Posted

技术标签:

【中文标题】捕获块未捕获异常【英文标题】:Catch block not catching exception 【发布时间】:2010-09-28 05:14:38 【问题描述】:

我有一个在 Load 事件处理程序中抛出 ApplicationException 的子表单(故意用于测试目的)。父窗体将 ChildForm.Show() 方法包装在 Try...Catch ex As Exception 块中。 catch 块只是显示一条消息并关闭子窗体。在 Visual Studio 2008 (.net 3.5 sp1) 中调试时,所有工作都按预期工作。但是,当我在 Visual Studio 之外运行它时,Catch 块似乎被遗漏了,并且发生了未处理的异常。知道这是为什么吗?

谢谢。

示例代码:

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim f2 As Form2

        f2 = New Form2

        Try
            MessageBox.Show("Opening form 2")
            f2.ShowDialog()
        Catch ex As Exception
            f2.Close()
            MessageBox.Show("Form 2 closed.")
        End Try
    End Sub

End Class

Public Class Form2

    Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Throw New ApplicationException("Test Form_Load")
    End Sub

    Public Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
    End Sub

End Class

堆栈跟踪:

System.ApplicationException: 在 WindowsApplication1.Form2.Form2_Load 测试 Form_Load(Object sender, EventArgs e) 在 UnhandledExceptionTest2\WindowsApplication1\Form2.vb System.Windows.Forms.Form.OnLoad(EventArgs e) System.Windows.Forms.Form.OnCreateControl() System.Windows.Forms.Control.CreateControl(布尔 fIgnoreVisible) System.Windows.Forms.Control.CreateControl() System.Windows.Forms.Control.WmShowWindow(Message& m) 在 System.Windows.Forms.Control.WndProc(Message&> m) 在 System.Windows.Forms.ScrollableControl.WndProc(Message&> m) 在 System.Windows.Forms.ContainerControl.WndProc(Message&> m) 在 System.Windows.Forms.Form.WmShowWindow(Message&> m) 在 System.Windows.Forms.Form.WndProc(Message&> m) 在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&> m) 在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&> m) 在 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr 参数)

【问题讨论】:

是的——描述的很模糊...... 【参考方案1】:

Form.Load 事件的行为方式与 Windows 窗体中的大多数其他事件相同。它由消息循环调度,在这种情况下,当 Windows 发送 WM_SHOWWINDOW 消息时。消息循环中有一个异常处理程序,可防止未捕获的异常终止消息循环。该异常处理程序引发 Application.ThreadEvent 事件。默认事件处理程序显示未处理的异常对话框。

长话短说,您无法在按钮 Click 处理程序中捕获 Load 事件中引发的异常。除了在 Load 事件处理程序本身中捕获和处理异常之外,很难做到正确,我建议您向表单添加一个公共方法。像 Initialize() 这样的东西。将代码从 Load 事件移到该方法中。调用 Show() 方法后调用 Initialize(),现在可以捕获异常了。

【讨论】:

+1 谢谢!太糟糕了,只有一个糟糕的解决方法...更多代码 = 更多错误 ;-) 我多年来一直在编写“WinForms”,这是我第一次遇到这个问题。【参考方案2】:

我也有同样的问题。我最终所做的是捕获所有异常。在 C# 中:

Application.ThreadException += new ThreadExceptionEventHandler(MyHandler);

然后显示表格。

我很想知道是否有人有更好的解决方案。

【讨论】:

【参考方案3】:

我为 C# 道歉(我不知道 Vb 语法)

你在做这样的事情吗:

  ChildForm child = new ChildForm();
  try 
      child.Show();
  
  catch(Exception ex)
  .....

如果是这样,我相信 Load 事件会发生在 New 上,而不是 Show(); (节目会触发激活)

【讨论】:

当我在调试器中单步执行时,Load 事件发生在 Show() 上。【参考方案4】:

新窗口有自己的线程,它自己加载。要验证这一点,您可以尝试在异常之前将 Thread.Sleep 放入 Form2_Load 几秒钟。在您遇到异常之前,您的主线程窗口应该继续执行。

【讨论】:

可以理解,为什么代码在 Visual Studio 中的工作方式与在 VS 之外运行时不同? 嗯...我错过了它调用的是 ShowDialog 而不是 Show,所以它应该阻塞。那就更令人费解了:-( 当我在 VS 之外运行程序时,使用 Attach to Process... 工具并打开 Threads and Call Stack 窗口,我观察到 Form2_Load 事件正在主线程上运行,并且调用堆栈显示 Form1_ButtonClick 调用 Form2_Load。然而,这种行为仍然存在。 查看 nobugz 和 mgilman 的 cmets,因为他们似乎在正确的轨道上。

以上是关于捕获块未捕获异常的主要内容,如果未能解决你的问题,请参考以下文章

python常见异常和异常捕获

Android 捕获全局异常CrashHandler,防止异常闪退,记录异常日志

java 主键异常怎么捕获

前端异常类型及捕获方式

lua中怎么捕获错误异常信息

lua中怎么捕获错误异常信息