C#如何取消订阅给定事件的所有事件处理程序?

C#如何取消订阅给定事件的所有事件处理程序?,c#,events,memory-leaks,C#,Events,Memory Leaks,有没有一种简单的方法可以遍历订阅给给定事件的所有处理程序?我的问题是,客户端订阅了,但忘记取消订阅,因此发生了内存泄漏。我需要一种方法,使对象在Dispose方法中断开其事件的所有处理程序,以便不会发生泄漏-至少不会因为事件而发生泄漏。将null设置为事件:MyEvent=null 但让客户取消订阅您的活动确实更好。另一种方法是使用所谓的“弱委托”模式。使用此技术时,事件仅使用WeakReference引用客户端,而不会将它们保留在内存中。当客户端不再从应用程序的其他部分引用时,它们将被垃圾收集

有没有一种简单的方法可以遍历订阅给给定事件的所有处理程序?我的问题是,客户端订阅了,但忘记取消订阅,因此发生了内存泄漏。我需要一种方法,使对象在Dispose方法中断开其事件的所有处理程序,以便不会发生泄漏-至少不会因为事件而发生泄漏。

将null设置为事件:
MyEvent=null


但让客户取消订阅您的活动确实更好。

另一种方法是使用所谓的“弱委托”模式。使用此技术时,事件仅使用
WeakReference
引用客户端,而不会将它们保留在内存中。当客户端不再从应用程序的其他部分引用时,它们将被垃圾收集(当收集客户端时,处理程序也可以自动注销)

这通常用于解决客户端“忘记”取消订阅.NET活动的问题,因此听起来这可能非常适合您的问题

  • 杜辛·坎贝尔有一个不错的选择
  • 我也喜欢这个,它讨论了大多数场景
  • 也在WPF中使用,但这种方法(对我来说)似乎有点复杂

只有当另一个对象(侦听器)在您的对象(事件源)之前死亡时,才会发生内存泄漏。在这种情况下,事件源仍然保留对侦听器的引用,这会阻止收集侦听器。当事件源死亡时,也可以收集未订阅的侦听器

若事件源在侦听器之前死亡,当对它的所有其他引用都设置为null时,这不会阻止以后收集侦听器


这意味着,事件源处理方法不是解决此问题的正确方法。它只能在侦听器代码中解决。简单地说,除了要求客户编写干净的代码之外,你什么都做不了。

在撰写本文时,最准确的答案最不受欢迎

你可以使事件处理程序无效,但在它的所有者被破坏后,它将被破坏——超级整洁并没有错,但正如Alex所说,问题不在这里

毫无疑问,Adi的源类将允许在收集监听对象时收集监听对象。所以问题是Adi的源对象一直保持开放状态,可能来自于其客户代码中的一些长链引用

下面的博文还介绍了Adi正在描述的一个解决方案,并解释了为什么它没有必要


在C#中,不可能将事件设置为null。实际上,如果您在声明事件的类中,则可以设置为null。将
MyEvent=new MyEvent()
设置为null不是更好吗??然后,当再次订阅时,您将不会得到null异常。@Mateusz:event字段为null,如果没有人订阅它,则触发事件的代码在访问之前应始终进行null检查event@Mateusz无论如何,阿迪提到他想用Dispose方法取消订阅。所以他不再使用这个物体了。