我试图在下面的代码中找出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还是只会坐在那里占用内存?
答案 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对象仅用于分配内存。