0

我有一个使用控件列表构建的表单。但是,它们通过删除和重建这些控件来刷新这些控件中的数据。这就是它变得敏感的地方。当我第一次单击另一个文本框时发生错误,该文本框触发了前一个文本框的离开事件,该文本框调用清理功能以重建所有控件。单击的文本框包含在已销毁项目的列表中,这就是发生错误“无法访问已处理的对象命名”的原因。但是,我只是不知道在哪里处理 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,但似乎 leave 或 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
4

1 回答 1

0

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

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

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

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

于 2012-07-11T13:43:45.303 回答