从父控件/表单中完全删除控件的正确方法是什么?

时间:2011-12-09 15:21:36

标签: vb.net user-controls dispose destroy

我的应用程序中有一个UI元素,其中Panel用于托管几个潜在的自定义UserControl之一。 Panel本身托管在标准化的UserControl中,我使用的是非模态对话框,我称之为“窗格”。

我使用的方法是实例化标准窗格的新实例,然后用逻辑使用Panel.Controls.Add(control)实例化其中的几个可选托管控件之一。然后,我将新窗格添加到设置位置的界面控件中,再次使用Control.Controls.Add(control),然后添加control.BringToFront()以最大化其z位置。

这一切都运作良好,但是当隐藏窗格并销毁它时,我似乎无法完全摆脱它。最初我只是使用Control.Controls.Remove(control)并将窗格的Parent属性设置为Nothing。这将使窗格消失所需的效果,我的假设是现在控件未被引用,GC将处理它。

然而,我所看到的是,当下一个外部托管TabControl更改标签页时,控件仍会立即显示在屏幕上,这意味着它仍然存在于某处。我可以确认这不是一个图形问题,并且窗格对象仍然使用VS Watch窗口的'Make Object ID'。 (至少我认为这是证据,没有代码可访问的引用,我仍然可以直接看到对象及其属性继续存在。)

我试过替换

Control.Controls.Remove(pane)
pane.Parent = Nothing

pane.Dispose()
GC.Collect()

我可以确认的Dispose调用都将控件从其父控件集合中删除,并将其Parent属性设置为Nothing,但似乎不再执行。它在强制GC后仍然存在,并且偶尔会在屏幕上出现blits。

这一切都导致了我原来的问题,在达到目的后删除和完全销毁控件的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

根据MSDN上的this文章,您可能会遇到来自最终化队列中对象的副作用。

  

Dispose方法应该为它正在处理的对象调用GC.SuppressFinalize方法。如果对象当前在终结队列中,GC.SuppressFinalize将阻止调用其Finalize方法。

翻译:未调用finalize方法,因此与您的控件关联的资源不会被释放。经过一番挖掘,我发现你应该

  

在释放对Component的最后一个引用之前,请始终调用Dispose。否则,在垃圾收集器调用Component对象的Finalize方法之前,不会释放它正在使用的资源。

来自this文章。

因此,您需要释放最后一个引用,或者需要直接调用components finalize方法,这样GC.Collect()才能正常工作。