将所有标准事件处理程序替换为WeakEventManager或其varian是否安全?

标准事件处理程序(带有运算符+ = )是内存泄漏原因之一(如果它没有未注册/处置(使用– =运算符))。
微软用WeakEventManager及其inheritance解决了它: 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.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(); } 

输出是:

一个

+++++++
一个

+++++++

我们可以看到析构函数不会被调用。 但是如果我们改变(通过评论未使用的代码):

  EventCaller.MyEvent += OnCall; 

  System.Windows.WeakEventManager.AddHandler(null, "MyEvent", OnCall); 

输出是:

一个

+++++++

+++++++
析构函数
B析构函数

在a为空之后,将不再调用其事件处理程序。
如果没有 – =运算符,A和B将在不再使用后处理。

1.我可以安全地用System.Windows.WeakEventManager替换所有+ =运算符,以避免由于可能缺少事件注销而导致的内存泄漏,并且保存代码不应该实现IDisposable吗?

2.如果不安全,我应该考虑或注意什么?

我可以安全地用System.Windows.WeakEventManager替换所有+ =运算符,以避免由于可能缺少事件注销而导致的内存泄漏,并且保存代码不应该实现IDisposable吗?

你能? 大概。 你应该? 可能不是。 如果您确实对事件处理程序有强引用,那么如果事件的发布者比事件的订阅者长,而不是用弱事件替换强引用,则应该更喜欢取消订阅。 使用弱事件有副作用。 其中之一就是表演。 另一个是语义差异。 您可能希望参考以下问题和答案,了解为什么.NET Framework中的事件实现默认情况下不使用弱事件模式:

为什么C#中的事件实现默认情况下不使用弱事件模式?

当然,在某些情况下您应该使用弱事件模式。 其中一种情况是WPF中的数据绑定,其中源对象完全独立于侦听器对象。 但这并不意味着你应该总是使用弱事件模式。 它也并不意味着您应该停止关注在您的应用程序中处理订阅。

1)我不会将代码保存作为参数来使用WeakEventManager而不是实现IDisposable。

2)在弱事件模式的情况下,事件处理将继续,直到垃圾收集器收集监听器。 取消引用侦听器不会立即停止事件处理 ,因为在Dispose模式中显式取消注册强引用事件处理程序。

3)请参阅有关弱事件模式的Microsoft文档

只要侦听器需要注册事件,就可以使用弱事件模式,但侦听器不会明确知道何时取消注册。 只要源的对象生存期超过侦听器的有用对象生存期,也可以使用弱事件模式。 (在这种情况下,有用的由您决定。)

如果您明确知道何时取消注册侦听器,我更喜欢标准事件并实现Dispose模式。 从事件处理程序的角度来看,显式取消注册的优点是,在弱事件模式继续处理事件(也可能是CPU和内存消耗)之前,事件处理会立即停止,直到垃圾收集器收集侦听器。