VB.Net中集合中对象的生命周期

时间:2010-11-16 13:55:15

标签: vb.net collections garbage-collection tabcontrol lifetime

我试图在下面的代码中找出tmpTabPages的生命周期。让我们假设表单有一个名为MyTabControl的空TabControl,它有一个名为NameCollection的字符串集合。

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    For Each itm In NameCollection
        Dim tmpTabPage as New TabPage(itm.toString)

        'Add Controls to tmpTabPage

        MyTabControl.TabPages.Add(tmpTabPage)
    Next
End Sub

由于tmpTabPage的范围是For / Next块,通常它的生命周期是直到块的结尾对吗?但是因为它被添加到具有块之外的范围的集合中它是否与集合具有相同的生命周期,或者在这种情况下是MyTabControl?最后,如果我调用MyTabControl.TabPages.Clear会破坏集合中的tmpTabPages还是只会坐在那里占用内存?

4 个答案:

答案 0 :(得分:5)

从Control(包括TabPage)派生的类的重要事项是Dispose()方法。它们不受自动垃圾收集的影响,Winforms保留一个内部表,将控件的句柄映射到控件引用。这就是为什么,即使你的程序没有引用它,你的主表单不会突然收集垃圾。

将TabPage添加到TabControl的集合中可以自动处理。这同样适用于TabControl,它将被添加到窗体的Controls集合中。正常的事件链是您的程序或用户关闭表单。 Form类迭代其子控件并调用它们的Dispose()方法。 TabControl在Dispose()方法中执行相同的操作,处理选项卡页面。 Windows窗口在此过程中被销毁,从该映射表中删除Handle,现在允许垃圾收集器最终收集控件的托管包装器。

有一个讨厌的陷阱让许多Winforms程序员陷入困境。如果从其父集合中删除控件,则您有责任自行处理它。删除它会自动处理它。 Winforms通过暂时将控件重新设置为名为“停放窗口”的隐藏窗口来使本机窗口保持活动状态。不错的功能,它允许您将控件从一个父项移动到另一个父项,而不必销毁和重新创建控件。

但关键词是“暂时”。如果您下次重新控制该控件,则只是暂时的。因此它会从停车窗口移动到新的父窗口。如果你实际上没有重新表现它,它将在停车窗口永远活着。吞噬资源直到程序终止。这也称为泄漏。当Windows在您已经创建了10,000个窗口时拒绝创建另一个窗口时,它可能会导致程序崩溃。

ControlCollection.Clear()方法在这里特别有害。它处理控件,它们都被移动到停车窗口。如果不是这样,很少,你必须自己调用Dispose()。

答案 1 :(得分:3)

当无法获取垃圾时,.NET中的对象就有资格进行垃圾收集。在这种情况下,成为通过TabPage集合访问TabPages的方式,直到从集合中删除它或标签控件本身才有资格收集

现在当一个对象有资格进行垃圾收集时,这并不意味着它会立即收集垃圾 - 根据一些相当复杂的启发式方法,垃圾收集会在不同的时间运行,并且还有“几代”的内存可以生成东西更难预测。

但基本上是:

  • 您无需担心已添加到集合中的对象会被神秘收集并导致问题
  • 您通常不必担心对象会永久泄漏内存。在某些情况下,当您需要采取一些有效步骤以确保在您不再使用该对象时,该对象有资格进行收集,但它们相对罕见。 (根据我的经验,它们通常与静态变量和/或事件有关。)

答案 2 :(得分:0)

因为soemthing引用了它们不会被处理的控件。

是的,如果您没有在合并中添加对它们的引用,则生命周期将持续到程序结束。

clear将从集合中删除对象,如果没有其他对它们的引用(在你描述的情况下会出现这种情况),它们将被收集垃圾。

答案 3 :(得分:0)

只将TabPage对象的引用添加到集合而不是对象TmpTabPage。在这种情况下,tmpTabPage对象仅用于分配内存。