Vb.net 在dispose上以编程方式将win forms用户控件设置为nothing

Vb.net 在dispose上以编程方式将win forms用户控件设置为nothing,vb.net,winforms,reflection,memory-leaks,Vb.net,Winforms,Reflection,Memory Leaks,我有vb.net winforms应用程序。它有由第三方控件引起的内存泄漏。我可以选择减少而不是消除内存泄漏 表单中有多个用户控件声明为Friend WithEvents。当窗体关闭时,它们不会被GCed,因为窗体在内存中,并且它保存了对用户控件的引用。但是,当我在dispose上将用户控件引用设置为nothing时,内存泄漏就会减少 现在我想把它扩展到整个应用程序,而不是一个表单。如何使用反射扫描所有用户控件,并在dispose中将它们设置为nothing(无)?有趣的是,用户控件是使用“Fr

我有vb.net winforms应用程序。它有由第三方控件引起的内存泄漏。我可以选择减少而不是消除内存泄漏

表单中有多个用户控件声明为Friend WithEvents。当窗体关闭时,它们不会被GCed,因为窗体在内存中,并且它保存了对用户控件的引用。但是,当我在dispose上将用户控件引用设置为nothing时,内存泄漏就会减少


现在我想把它扩展到整个应用程序,而不是一个表单。如何使用反射扫描所有用户控件,并在dispose中将它们设置为nothing(无)?有趣的是,用户控件是使用“Friend WithEvents”签名声明的。是否可以在扫描时以某种方式使用此选项?

正如@puropoix所述,如果您处置该控件,它将使其子控件失效并处置。如果您认为它们使用的是动态控件,您可以递归地处理这些控件吗

Sub DisposeControls(parentControl as Control)
    For each control as Control in parentControl.Controls 
        If control.HasChildren() Then Call Me.DisposeControls(control) 
        control.Dispose()
    Next
End Sub

编辑:应该提到的是,我不确定上面的代码是否会编译-将其视为伪代码。

正如@puropoix所述,如果您处置该控件,它将失效并处置其子控件。如果您认为它们使用的是动态控件,您可以递归地处理这些控件吗

Sub DisposeControls(parentControl as Control)
    For each control as Control in parentControl.Controls 
        If control.HasChildren() Then Call Me.DisposeControls(control) 
        control.Dispose()
    Next
End Sub

编辑:应该提到的是,我不确定上面的代码是否会编译-将其视为伪代码。

我最终这样做了。这不是最佳的,但它的工作真的很好。我所有的表单都继承了一个基本表单。在该形式的disposed方法中,我使用了这个反射代码

Private Sub BaseForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
    NullifyReferencesOnDispose()
    RemoveHandler Me.Disposed, AddressOf BaseForm_Disposed
End Sub

Protected Overridable Sub NullifyReferencesOnDispose()
    Dim typ = CType(Me.GetType, Reflection.TypeInfo)
    For Each fld In typ.DeclaredFields
        fld.SetValue(Me, Nothing)
    Next
End Sub

最后我做了这个。这不是最佳的,但它的工作真的很好。我所有的表单都继承了一个基本表单。在该形式的disposed方法中,我使用了这个反射代码

Private Sub BaseForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
    NullifyReferencesOnDispose()
    RemoveHandler Me.Disposed, AddressOf BaseForm_Disposed
End Sub

Protected Overridable Sub NullifyReferencesOnDispose()
    Dim typ = CType(Me.GetType, Reflection.TypeInfo)
    For Each fld In typ.DeclaredFields
        fld.SetValue(Me, Nothing)
    Next
End Sub

您不需要反射,只需处置您创建的任何控件即可。如果其他控件是实际的UserControl,则其子控件的处理是内置的(除非它们也执行动态控件)。您不需要反射,只需对您创建的任何控件进行
Dispose
。如果其他的东西是一个实际的用户控件,那么处理它的子控件是内置的(除非它们也在做动态控件)。代码是可靠的,但是它对内存问题没有帮助。将用户控件refs设置为null仍然不能减少内存,这真的很有趣!这可能是因为第三方控件库已经覆盖了dispose的基本功能,并且没有按照本文实现CloseHandle来处理非托管资源。感谢您添加您的答案作为解决方案,很高兴看到您是如何获得结果的!代码是可靠的,但它无助于解决内存问题。将用户控件refs设置为null仍然不能减少内存,这真的很有趣!这可能是因为第三方控件库已经覆盖了dispose的基本功能,并且没有按照本文实现CloseHandle来处理非托管资源。感谢您添加您的答案作为解决方案,很高兴看到您是如何获得结果的!