【问题标题】:Event handler and memory leaks事件处理程序和内存泄漏
【发布时间】:2011-01-13 12:47:47
【问题描述】:

我分析了一个 VB.NET 项目,有一些对象(子 MDI 表单)已被释放,但未被 GC 删除。

MemoryProfiler 分析发现以下内容:

"这个实例已经被释放并且仍然 由 EventHandler 间接植根。 这往往表明 EventHandler 一直没有正确 删除,是一个常见的原因 内存泄漏。下面的实例是 直接由 EventHandler(s) 根植。 调查他们以获得更多 有关此问题的信息...”

现在,我试图弄清楚这意味着什么以及如何解决它。

我有一个 MDI 表单和一个子表单。 GC 在打开/关闭后不会收集子表单,显然是因为 MDIForm EventHandlerList...

引用的仍然(间接?)

这是什么问题,我该如何解决?

我尝试了this thread 中推荐的修复,因为PropertyStore 中的MDI 引用有问题,现在已消除,但出现了MDI EventHandlerList 对子窗体的引用...

经过一些代码分析,我观察到了一些

AddHandler newMenu.Click, AddressOf ClickMenu

前面没有RemoveHandler newMenu.Click, AddressOf ClickMenu。会不会是主要原因?

还有一个建议是Handles

Private Sub ClickMenu(sender as Object, e as EventArgs) Handles newMenu.Click

更好

RemoveHandler newMenu.Click, AddressOf ClickMenu
AddHandler newMenu.Click, AddressOf ClickMenu

从内存分配的角度看?

【问题讨论】:

  • 截取代码可能会有所帮助。特别是添加和删除事件处理程序以及处置代码。
  • 在 dispose 之后调用 GC.Collect() 有什么不同吗?仅仅因为某些东西被丢弃并不总是意味着它会立即被垃圾收集。
  • 另外..这真的有问题吗?阅读您链接到的论坛表明,随着时间的推移,情况不会变得更糟。通过 MS 代码泄露的几 kb 会产生那么大的影响吗?
  • 这是个问题。实际上,每次我打开一个子窗体时,内存都会增加大约。每个子窗体打开时 1MB。

标签: .net .net-2.0 memory-leaks event-handling


【解决方案1】:

EventHandlerList 由提供大量事件的类使用,以便通过仅在需要而不是在声明事件时为事件支持字段分配空间来更有效地处理内存。因此,主窗体的所有事件都存储在那里。

我希望子窗体正在监视其父窗体何时可能关闭(这是一个常见用例),并且它在收到该事件时没有取消订阅 FormClosingFormClosed 事件。然而,这只是一个猜测。要确认,请查看您的子表单实现并找到它订阅父表单事件的所有情况,然后确保这些事件有相应的取消订阅。

更新
您发现的未删除的菜单处理程序很可能是您看到的问题的根源。尝试添加 remove 调用,看看是否解决了泄漏问题。

【讨论】:

    【解决方案2】:

    还有另一个对象引用了应该由 GC 通过事件处理程序删除的对象。含义:还有另一个对象仍订阅已处置对象的事件。

    当您想要处置该对象时,您可以通过取消订阅事件(从事件中删除事件处理程序)来解决此问题。

    【讨论】:

      猜你喜欢
      • 2012-05-31
      • 2012-10-29
      • 1970-01-01
      • 2012-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-02
      相关资源
      最近更新 更多