【问题标题】:Can not access a disposed object named "TextBox" (Leave And MouseDown Event) (How to handle System.ObjectDisposedException)无法访问名为“TextBox”的已处置对象(Leave 和 MouseDown 事件)(如何处理 System.ObjectDisposedException)
【发布时间】:2012-07-11 03:27:57
【问题描述】:

我有一个由控件列表构建的表单。但是,他们通过删除和重建这些控件来刷新这些控件中的数据。这就是它变得敏感的地方。当我第一次单击另一个文本框时发生错误,该文本框触发了前一个文本框中的离开事件,该文本框调用清理功能以重建所有控件。单击的文本框包含在已销毁项目列表中,这就是错误“无法访问已命名的已处置对象”发生的原因。但是,我只是不知道在哪里处理 System.ObjectDisposedException 因为我无法在创建表单时捕获它。

这是崩溃日志

 System.ObjectDisposedException: Can not access a disposed object named "TextBox".
Object name: "TextBox".
    Has System.Windows.Forms.Control.CreateHandle ()
    Has System.Windows.Forms.TextBoxBase.CreateHandle ()
    Has System.Windows.Forms.Control.get_Handle ()
    Has System.Windows.Forms.Control.set_CaptureInternal (Boolean value)
    Has System.Windows.Forms.Control.WmMouseDown (Message & m, MouseButtons button, Int32 clicks)
    at System.Windows.Forms.Control.WndProc (Message & m)
    Has System.Windows.Forms.TextBoxBase.WndProc (Message & m)
    Has System.Windows.Forms.TextBox.WndProc (Message & m)
    Has System.Windows.Forms.ControlNativeWindow.OnMessage (Message & m)
    Has System.Windows.Forms.ControlNativeWindow.WndProc (Message & m)
    at System.Windows.Forms.NativeWindow.Callback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

我也尝试使用声明 if Control.Isdisposed then return 但似乎离开或 mousedown 事件并不关心它:S

你们能帮我找到我可以在这个表单上处理这个错误的地方吗? 我无法通过调试来跟踪它,它只是在 End Sub 之后弹出。

在 vb.net FrameWorks 1.1 中编码

这是我销毁目标对象的代码

Private Sub viderRecursiveStack(ByVal control As Control)
        Dim stack As New stack
        Dim ctl As control
        Dim enfantAssocie As ArrayList


        stack.Push(control)

        While stack.Count > 0

            ctl = CType(stack.Pop, control)


            If Not ctl Is Nothing Then

                If TypeOf ctl Is Panel Then

                    'Cree la liste des enfants associés
                    enfantAssocie = New ArrayList(ctl.Controls)

                    For Each ctli As control In enfantAssocie

                        If Not TypeOf ctli Is EasyDeal.Controls.EasyDealLabel3D AndAlso** Not TypeOf ctli Is EasyDeal.Controls.EasyDealButton Then
                            stack.Push(ctli)
                            ctl.Controls.Remove(ctli)
                        End If

                    Next

                Else
                    RemoveHandler ctl.Leave, AddressOf txtEquipAddCommissionChanged
                    ctl.Dispose()
                End If

            End If

        End While

    End Sub

【问题讨论】:

  • 正如@SteveDog 建议的那样,您可以绕过这个错误,但代码将非常脆弱,并且很可能依赖于 Windows 和框架版本。如果是我,我会试图找到另一种描述你想要的行为的方式。
  • 我明白了,如果可能的话,我想自己处理 System.ObjectDisposedException!
  • 这不是您可以处理的异常,它是您代码中的错误。表单的成员,如“TextBox1”,正在引用已释放的控件。不要在上面贴创可贴,修复错误。例如,重新运行 InitializeControls() 应该可以修复它。
  • 帕桑特先生对这一点是正确的(也是:)),充其量你会解决一个症状。在代码附近嗅探,例如在某处添加另一个事件处理程序,它会再次中断。

标签: vb.net events exception controls dispose


【解决方案1】:

当您“删除”一个控件时,您应该执行以下所有操作,并按以下顺序执行:

  1. 从控件中删除所有事件处理程序
  2. 从父Controls集合中的控件中移除控件
  3. 在控件上调用Dispose方法

但是,在这种情况下,您正在做所有这些事情,但您仍然遇到问题,因为您正试图从它自己的事件中删除控件。如果您想首先避免出现异常,我建议在这种情况下等待对该控件调用 dispose 直到稍后时间。在第 2 步之后,您可以将控件添加到名为 _controlsToDispose As List(Of Control) 的私​​有字段中。然后,在表单的卸载事件、计时器或来自其他控件的其他事件中,您可以遍历该列表中已排队等待处置的任何控件,然后对其进行处理。

但是,如果您想保持原样并在异常发生时忽略异常,您应该能够在您的 MyApplication_UnhandledException 事件处理程序中执行此操作。要到达那里,请打开您的项目属性,转到“应用程序”选项卡,然后单击页面底部应用程序框架框架中的“查看应用程序事件”按钮。但是,这仅在您启用了应用程序框架时才可用。如果您已经为应用程序创建了自己的入口点并且您自己调用了Application.Run,那么您应该能够在该调用周围放置一个try catch 块来捕获它。

【讨论】:

  • 我用递归堆栈正确清理我的控件并从中删除我的处理程序
  • 那么表单上真的没有办法处理这个吗?
  • 没有。异常由 WndProc(窗口消息循环)调用的框架代码在内部引发。换句话说,它正在处理 WM_MOUSE_DOWN 消息并且在 Microsoft 的一个对象中失败,因为框架假定当前控件不会被其自己的事件处理程序释放。
  • Exception 中是否有任何 on 信息可以让我了解发送者事件信息的基本信息或其他信息?
  • 定义“发送者事件信息”。我不确定你的意思。
猜你喜欢
  • 2023-03-23
  • 1970-01-01
  • 2019-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多