我正在研究如何正确创建弱引用事件处理程序。由于WPF已经有一个避免事件内存泄漏的解决方案,我反编译了“WeakEventManager”类并花了一些时间来分析它。
正如我所知,“WeakEventManager”类依赖于创建和存储对目标对象以及事件处理程序委托的弱引用。以下是一些代码段:
this._list.Add(new WeakEventManager.Listener(target, handler));
public Listener(object target, Delegate handler)
{
this._target = new WeakReference(target);
this._handler = new WeakReference((object) handler);
}
我问自己这个简单的解决方案是否已经有效或者我忽略了一个重要方面,因为我在互联网上找到的大多数其他解决方案都很复杂且难以理解。到目前为止我能找到的最佳解决方案 使用未绑定的委托。这是某种包装器委托,它将事件处理程序和事件订阅者实例作为参数(是的,它要求在委托调用期间传递事件订阅者对象)。
你可以在这里找到这篇好文章:
http://diditwith.net/CommentView,guid,aacdb8ae-7baa-4423-a953-c18c1c7940ab.aspx#commentstart
“WeakEventManager”类不依赖于了解订阅者类或任何其他信息。除此之外,它还可以与匿名代表合作。为什么开发人员花了这么多时间编写一个不仅工作而且使用方便的解决方案,如果解决方案只要求他们存储对委托的弱引用?有什么收获?
更新:因为有人对这个问题进行了贬低(可能有点不明确),我想提出一个更精确的问题:
最重要的是创建一个有效的弱事件处理程序吗?如果没有,缺少什么?
答案 0 :(得分:7)
我忽略了一个重要方面
是的,重要的一个。你换了另一个“泄漏”。您现在可以防止收集WeakReference对象,而不是阻止事件订阅者对象收集垃圾。你没有领先。
还需要什么才能让那些过时的WeakReferences得到清理。当IsAlive属性返回false时,您不再需要它们,然后将其从_list
中删除。但是你必须单独检查,某些代码需要处理它。一个明显的选择是检查何时添加事件或何时触发事件。但这还不够,因为客户端代码只会在初始化时添加,并且无法保证事件始终被触发。
所以某些类型的方案需要稍后再做。任何事都是可能的,没有什么是非常理想的,因为经常没有完成任何工作需要很多繁忙的工作。做出正确的选择很重要。这肯定包括不这样做,它往往是一个设计问题的创可贴。
答案 1 :(得分:1)
WeakEventManager
背后的想法是,它保留了一个对事件目标对象的弱引用列表以及它必须调用的处理程序列表,但不会将它们绑在一起" (直接订阅事件通常会这样做),允许对目标进行垃圾收集(并定期检查,以便在源被垃圾收集时相应地清空"订阅的#34;委托列表)。
这听起来很简单,需要大量的管道代码,并且所有WeakEventManager
都会这样做(以易于使用的方式为您做管道工作)。
如果您要将WeakEventManager
克隆到您自己的实现(或使用内置)并且这样做,那么是的,这就是您需要做的所有事情。如果那不是你问的问题,那么这个问题我不清楚。
答案 2 :(得分:0)
最重要的是创建一个有效的弱事件处理程序吗?如果没有,缺少什么?
这是最重要的一点,Listener
类的其余部分也很重要,更不用说支持这个非委托事件处理程序所需的手动管道。
例如,请查看ListenerList.DeliverEvent
,这比通常的Invoke
电话更复杂。
基本上,正常事件系统假设强引用,因此为了使用WeakReference
,您最终必须自己添加大量翻译逻辑,以及决定如何处理因使用{{{{{{{ 1}}。