有趣的事件“处置”的行为(Interesting event “Dispose” behaviour

2019-07-30 05:52发布

我已经在我们的.NET WinForms应用程序发现有趣的现象。 我们有很多有孩子的MDI添加MDI窗体。 这些子窗体听“广播”事件,在本质上是调用刷新itsself。 本次活动是在基类和子窗体添加监听事件的声明。

我注意到,即使这些子窗体关闭时,事件仍在打,如果没有明确的Dispose()方法删除该事件。

这背后的理由? 当然,如果关闭窗体时,事件应当被拆卸/设置的? 是不是因为实际的事件本身在外部类被声明? 这就是我假设。

有识之士将不胜感激。

(使用C#,.NET 3.5)

Answer 1:

本次活动,这仍然是在范围,因为它是在主窗体上,仍然要在子窗口委托的引用。 因此关闭窗口将不会出售的对象,因为它也仍然是在范围上通过此引用。 这是一种很常见的方式获得在.NET中的“内存泄漏”。 同时认为,因为孩子的窗口仍处于范围内的一切窗口内仍是在范围上,也不会得到收集。

至于为什么窗口不脱离上关闭所有的事件处理程序。 这将是如果它确实很奇怪的行为。 仅仅因为你已经关闭窗口并不意味着你完成它,你可以重新打开它,从它保存数据持久化状态。 调用close在窗口上有超过调用任何其他方法没有特殊属性,它不配置窗口,将其标记为收藏或其他任何东西。



Answer 2:

你是对的。 当您注册一个事件,你的窗体的引用被添加到事件委托(在拥有该事件的对象)。 除非你删除注册的,你的形式永远不会收集垃圾,因为它仍然有至少一个参考吧(委托),当引发事件发出与仍然是电话。

应始终确保事件得到退订,避免这种泄漏。



Answer 3:

是的,这是设计的行为,这也是为什么的原因WeakEvent图案concieved。



Answer 4:

您的事件订阅“计数”为您的孩子形式的参考。 (所以你的孩子的形式不被垃圾收集两种)。

要了解这是怎么回事,抬头就委托帮助。 它有一个叫做目标(对象类型)成员指向订户。 所以,你还是有一个参考链活着:

MDI父(事件发布) - >代理 - >您的孩子形式。

你必须清理的Dispose()事件的订阅或您的孩子的形式将永远不会有资格进行垃圾回收。

现在,如果你在网上的“弱裁判事件”周围一看,你会发现许多人都张贴定义弱事件的解决方法。 这里有一个例子: http://www.codeproject.com/KB/cs/weakeventhandlerfactory.aspx

我不得不原型之一,也是,我会很高兴,如果你想让它分享。 然而,我的建议是坚持定期事件和处置清理()。



文章来源: Interesting event “Dispose” behaviour