【问题标题】:programmatically set win forms user controls to nothing on dispose以编程方式将 win 表单用户控件设置为空置
【发布时间】:2017-05-08 18:47:50
【问题描述】:

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

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

现在我想将其扩展到整个应用程序,而不仅仅是一种形式。我将如何使用反射来扫描所有用户控件并将它们设置为空 dispose ?有趣的是,用户控件是使用“Friend WithEvents”签名声明的。是否可以在扫描时以某种方式使用它?

【问题讨论】:

  • 您不需要反射,只需 Dispose 您创建的任何控件。如果其他东西是实际的 UserControl,则内置处理其子控件(除非它们也在做动态控件)

标签: vb.net winforms reflection memory-leaks


【解决方案1】:

正如@Plutonix 所说,如果您处置该控件,它将使其子控件无效并处置。如果您认为他们正在使用动态控件,您可以递归地处理控件吗?

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

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

【讨论】:

  • 代码是可靠的,但它对内存问题没有帮助。将用户控件 refs 设置为 null 仍然不会减少内存
  • 这真的很有趣!可能是第 3 方控件库已经覆盖了 dispose 的基本功能,并且没有按照MSDN 文章实现 CloseHandle 来处理非托管资源。感谢您添加您的答案作为解决方案,很高兴看到您是如何取得结果的!
【解决方案2】:

我最终这样做了。它不是最佳的,但效果很好。我的所有表单都继承了基本表单。在那个表单的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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 2019-10-28
    相关资源
    最近更新 更多