【问题标题】:Lifetime of objects in a collection in VB.NetVB.Net 集合中对象的生命周期
【发布时间】:2010-11-16 22:39:14
【问题描述】:

我试图在以下代码中找出 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 会被销毁,还是只会占用内存?

【问题讨论】:

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


    【解决方案1】:

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

    将 TabPage 添加到 TabControl 的集合中会自动处理。 TabControl 也是如此,它将被添加到表单的 Controls 集合中。正常的事件链是您的程序或用户关闭表单。 Form 类迭代其子控件并调用它们的 Dispose() 方法。 TabControl 在它的 Dispose() 方法中做同样的事情,处理标签页。 Windows 窗口在此过程中被破坏,从该映射表中删除句柄,现在允许垃圾收集器最终收集控件的托管包装器。

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

    但是那里的关键字是“临时”。如果您下一次重新设置控件,这只是暂时的。所以它从停车窗口移动到新的父窗口。如果您实际上不重新设置它,那么它将在停车窗口上永远保持活力。吞噬资源直到程序终止。这也称为泄漏。当您已经创建了 10,000 个窗口时,如果 Windows 拒绝创建另一个窗口,它可能会使您的程序崩溃。

    ControlCollection.Clear() 方法在这里尤其有害。它确实处理控件,它们都被移到那个停车窗口。如果这不是故意的,很少会这样做,您必须自己对它们调用 Dispose()。

    【讨论】:

      【解决方案2】:

      .NET 中的对象在无法获取它们时就可以进行垃圾回收。在这种情况下,有一种方法可以通过 TabPages 集合访问 TabPage,直到它从集合中删除或选项卡控件本身符合收集条件。

      现在,当一个对象符合垃圾收集条件时,这并不意味着它会立即被垃圾收集 - 垃圾收集根据一些相当复杂的启发式算法在不同时间运行,并且还有“世代”的内存来制造东西更难预测。

      但基本上:

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

      【讨论】:

        【解决方案3】:

        因为某些东西引用了它们不会被释放的控件。

        是的,如果您不将对它们的引用添加到集合中,则生命周期将一直持续到过程结束。

        清除将从集合中删除对象,如果没有其他对它们的引用(在您描述的情况下不应该出现),它们将被垃圾收集起来

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            猜你喜欢
            • 2012-07-28
            • 1970-01-01
            • 2011-04-28
            • 1970-01-01
            • 1970-01-01
            • 2011-03-16
            • 1970-01-01
            • 2014-06-29
            相关资源
            最近更新 更多