【问题标题】:What is the correct way to fully remove a control from a parent control/form?从父控件/表单中完全删除控件的正确方法是什么?
【发布时间】:2012-01-16 20:56:02
【问题描述】:

我的应用程序中有一个 UI 元素,其中面板用于托管几个潜在的自定义用户控件之一。面板本身托管在一个标准化的用户控件中,我正在使用类似于非模态对话框的东西,我称之为“窗格”。

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

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

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

我已经尝试替换

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

pane.Dispose()
GC.Collect()

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

这一切都引出了我最初的问题,在它们达到目的后删除和完全销毁控件的正确方法是什么?

【问题讨论】:

  • 你确定pane.Dispose() 方法没有留下任何东西吗? EventHandler 或许?一些SqlConnection 开放?东西……
  • 这可能会导致另一个问题,我知道如果管理不当,使用“AddHandler”会留下一些混乱,是否存在“WithEvents”和“Handles”关键字可能会引入同样混乱的情况?
  • 我也有同样的问题,我希望自己能回答这个问题...
  • 第一个sn-p肯定是错的,面板永远泄漏。第二个 sn-p 绝对是正确的,减去了 Collect 调用。您在面板代码中为非面板或其子事件源订阅的任何事件都必须手动取消订阅。
  • 查看了所有后代代码后,我还没有实现任何“AddHandler”方法,所有事件都通过 WithEvents 和 Handles 关键字工作,至少在大多数正常情况下,我希望取消订阅自己自动。我想某处一定有一个虚假的参考,只是没有一个好的工具来找到它。

标签: vb.net user-controls dispose destroy


【解决方案1】:

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

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

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

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

来自this的文章。

所以要么你需要释放你的最后一个引用,要么你需要直接调用组件的 finalize 方法,这样你的 GC.Collect() 才能工作。

【讨论】:

    猜你喜欢
    • 2015-04-11
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    相关资源
    最近更新 更多