我正在阅读“The C# Language”,第 4 版,它谈到WeakReference
和Weak Event Pattern
:
CHRISTIAN NAGEL:内存泄漏通常是由于事件的错误使用造成的。如果客户端对象附加到事件但不与它们分离,并且不再使用对客户端对象的引用,则垃圾收集器仍然无法回收客户端对象,因为发布者的引用仍然存在。这可以通过 (1) 在不再使用客户端对象时分离事件,(2)使用持有委托的类的
add
和remove
访问器的自定义实现,或 (3) WPF 使用 IWeakEventListener 来避免界面。WeakReference
Weak Event pattern
我在这里有疑问:与“选项(1)显式分离事件”相比,选项“(2) WeakReference
”根本没有带来任何便利WeakReference
,因为使用仍然需要显式调用add
and remove
。
否则,即使事件处理程序的对象之一被分配为 null,“孤儿”对象仍将响应该事件 - 这将导致意外行为。
注意:WeakReference
仅以事件处理程序的对象不受事件发布者对象影响的方式帮助垃圾收集;WeakReference
不强制事件处理程序对象被垃圾收集。
类似的问题也适用于弱事件模式。
也许这有点抽象,以 Josh Smith 的 Mediator 模式(http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/)为例。
public class Mediator //...
{
public void Register(object message, Action<object> callback)
{
// notice: Mediator has no Unregister method
}
public void NotifyColleagues(object message, object parameter)
{
// ...
}
}
public class ObjectA //...
{
public string ObjectAText
{
get { return _objectAText; }
set
{
//...
_mediator.NotifyColleagues(MediatorMessages.ObjectASaidSomething, _objectAText);
}
}
}
public class ObjectB //...
{
//...
public ObjectB(Mediator mediator)
{
//...
_mediator.Register(
MediatorMessages.ObjectASaidSomething,
param =>
{
// handling event ObjectASaidSomething
});
}
}
如果我们有
ObjectA objectA = new ObjectA();
ObjectB objectB1st = new objectB();
objectA.ObjectAText = "John"; // objectB1st will respond to this event.
objectB1st = null; // due to delay of garbage collection, the object is actually still in memory
ObjectB objectB2nd = new objectB();
objectA.ObjectAText = "Jane"; // both objectB1st and objectB2nd will respond to this event!
由于WeakReference
?
但是如果Mediator
该类提供“Unregister”方法(实际上我实现了一个),“选项(2)WeakReference
”将与“选项(1)显式分离事件”没有区别。(Mediator 本身仍然是一个有用的模式,可以穿透 WPF 或 MVVM 组件层的层次结构)