【问题标题】:vb.net form not being disposedvb.net 表单未处理
【发布时间】:2016-03-10 21:00:06
【问题描述】:

我在 vb.net 中创建了一个简单的项目,其中包含 2 个表单“mainform”和“childform”。 “mainform”有一个按钮,可以简单地发出 childform.show(),而“childform”有一个按钮,可以发出 me.close() 和 me.dispose()。

当我运行项目时,它会显示主窗体。我单击按钮,它会打开子窗体。当我单击子窗体按钮时,它会关闭子窗体并且一切正常。

但是,当我使用 JetBrains dotMemory 对此进行分析时,我会在打开子窗体之前拍摄一张快照,然后在打开和关闭它之后再拍摄一张。我比较了快照,它显示了一个仍然存在的子窗体实例。当我查看依赖链时,我发现它通过“MyProject+MyForms”的实例保持活动状态。

如果我多次打开和关闭子窗体并重新快照,则子窗体的一个实例仍然存在。

谁能解释这里发生了什么?

【问题讨论】:

  • 我想我已经弄清楚这里发生了什么。因为我使用 childform.Show() 而不是 Dim form 作为新的 childform 和 form.Show() 显示了 childform,所以在幕后创建了 childform 的新实例以及对它的引用。这确实表明,使用这种显示表单的简写方式本质上会创建一个无法处理的对象,因此会产生少量泄漏(尽管它只会在内存中保留一个子表单和相关资源)。我不确定这是否清楚。我通常会使用 create new / show。
  • 我通常在全局空间中声明一个子窗体,所以我在主窗体中只有一个子窗体实例。这样我就不必每次打开表单时都重新构建表单。这也保留了表单设置,因此 AI 可以关闭表单并打开获取相同的属性。
  • Close 和 Dispose 都不会使对象消失,它们只会破坏非托管对象。在垃圾收集器运行之前,该对象不会消失。 MyProject.MyForms 是 VB.NET 的一项功能,它支持古怪的语法,允许您使用类型名称而不是使用 New 关键字创建实例。当您使用 Form2.Show() 而不是 Dim frm As New Form2 时会发生这种情况:frm.Show()。所以这一切都很正常。
  • 汉斯的评论是正确的答案。在 VB.NET 中,无论您喜欢与否,都可以通过表单的类名获得一个实例。 :)
  • 只有在您执行第一个 Show()(或类似操作)时才会创建一个实例。这是有道理的,但我喜欢汉斯使用“古怪”这个词。我认为 Hans 说“只销毁非托管对象”有点不正确,因为实际上将继续显示一个没有引用的可见表单(因此必须在某处有一个引用以阻止它被垃圾收集),无论 Close 做什么也必须使其符合条件用于垃圾收集。

标签: c# vb.net


【解决方案1】:

您的主窗体中仍有对子窗体的引用,因此垃圾收集器不会将其从内存中删除。

请注意,这与Dispose() 无关。

只要有对对象的引用,它就不会被收集。

【讨论】:

  • 这个我明白了,这是一个引用被创建的事实。当我调用 childform.Show() 时,框架正在创建一个实例并使其可见。我不确定为什么它会持久存储引用,并且确实记录了这种行为。答案显然是“不要这样做”,但这并不明显。而且它的存储位置并不明显
  • @Gwynge。 Here's 简短解释为什么它在那里。主要用于将 vb6 代码转换为 vb.net 并使 vb6 程序员更容易跳转到 .net
【解决方案2】:

您的嵌套类 MyForms 有一个字段 m_ChildForm,您出于某种原因在其中放置了对 ChildForm 类实例的引用。此引用可防止 ChildForm 对象被收集。在关闭子窗体时将此字段设置为 null 或根本不将引用存储在类字段中。

【讨论】:

    猜你喜欢
    • 2013-08-10
    • 2012-11-24
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多