【发布时间】: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 做什么也必须使其符合条件用于垃圾收集。