标准事件处理程序(使用 operator +=
)是内存泄漏原因之一(如果它不是未注册/处置(使用-=
operator))。
WeakEventManager
微软用它的继承解决了它,比如:PropertyChangedEventManager, CollectionChangedEventManager, CurrentChangedEventManager, ErrorsChangedEventManager
等等。
内存泄漏的简单示例代码是:
public class EventCaller
{
public static event EventHandler MyEvent;
public static void Call()
{
var handler = MyEvent;
if (handler != null)
{
handler(null, EventArgs.Empty);
Debug.WriteLine("=============");
}
}
}
public class A
{
string myText;
public A(string text)
{
myText = text;
EventCaller.MyEvent += OnCall;
// Use code below and comment out code above to avoid memory leakage.
// System.Windows.WeakEventManager<EventCaller, EventArgs>.AddHandler(null, "MyEvent", OnCall);
}
void OnCall(object sender, EventArgs e)
{
Debug.WriteLine(myText);
}
~A()
{
Debug.WriteLine(myText + " destructor");
}
}
void Main()
{
var a = new A("A");
var b = new A("B");
EventCaller.Call();
a = null;
GC.Collect();
EventCaller.Call();
}
输出是:
A
B
+++++++
A
B
+++++++
我们可以看到析构函数不会被调用。但是如果我们改变(通过注释未使用的代码):
EventCaller.MyEvent += OnCall;
到
System.Windows.WeakEventManager<EventCaller, EventArgs>.AddHandler(null, "MyEvent", OnCall);
输出是:
A
B
+++++++
B
+++++++
A destructor
B destructor
在 A 为空之后,它的事件处理程序将不再被调用。A 和 B 将在没有操作员的情况下不再使用后被处理掉-=
。
我可以安全地替换所有 += 运算符,
System.Windows.WeakEventManager
以避免由于可能缺少事件注销和保存代码而导致的内存泄漏,应该不实现IDisposable
?如果它不是真的安全,我应该考虑或注意什么?