简体   繁体   English

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

[英]C# How to unsubscribe all event handlers from a given event?

Is there a simple way to iterate all over the handlers subscribed to a given event? 有没有一种简单的方法可以遍历订阅给定事件的所有处理程序? My problem is that clients subscribe but forget to unsubscribe so a memory leak happens. 我的问题是客户端订阅但忘记取消订阅,因此发生了内存泄漏。 I need a way for an object to disconnect all the handlers of its events in the Dispose method so a leak would not happen - at least not because of events. 我需要一种方法来使对象在Dispose方法中断开其事件的所有处理程序,以便不会发生泄漏-至少不是由于事件引起的。

Set null to your event: MyEvent = null; 将事件设置为null: MyEvent = null;

But it is really better to make clients unsubscribing from your event. 但是,最好让客户退订您的活动。

An alternative approach is to use so-called "weak delegate" pattern. 另一种方法是使用所谓的“弱委托”模式。 When you use this technique, the event references clients only using WeakReference which doesn't keep them in memory. 使用此技术时,事件仅使用WeakReference引用客户端,而不WeakReference其保留在内存中。 The clients will be garbage collected when they are no longer referenced from other part of the application (and the handler can be also unregistered automatically when the client is collected). 当不再从应用程序的其他部分引用客户端时,这些客户端将被垃圾回收(收集客户端时,处理程序也可以自动取消注册)。

This is usually used to solve the problem with clients "forgetting" to unsubscribe from a .NET event, so it sounds like this might be well suited for your problem. 这通常用于解决客户端“忘记”取消订阅.NET事件的问题,因此听起来这可能非常适合您的问题。

Memory leak happens only if another object (listener) dies before your object (event source). 仅当另一个对象(侦听器)在您的对象(事件源)之前死亡时,才会发生内存泄漏。 In this case, event source still keeps the reference to listener, which prevents listener to be collected. 在这种情况下,事件源仍保留对侦听器的引用,这将阻止收集侦听器。 When event source dies, unsubscribed listener may be collected as well. 当事件源死亡时,也可以收集未订阅的侦听器。

If event source dies before listener, this does not prevent listener to be collected later, when all other references to it are set to null. 如果事件源在侦听器之前死亡,则当对它的所有其他引用都设置为null时,这不会阻止稍后收集侦听器。

This means, event source Dispose method is not correct place to solve this problem. 这意味着,事件源Dispose方法不是解决此问题的正确位置。 It may be solved only in a listener code. 它只能在侦听器代码中解决。 Simply talking, you cannot do anything, except asking your clients to write clean code. 简单地说,除了要求您的客户编写干净的代码外,您无能为力。

At the time of writing, the most accurate answer is the least popular. 在撰写本文时,最准确的答案是最受欢迎的答案。

You can nullify the event handler but this would be zapped anyway after its owner is zapped - its not wrong to be super tidy, but like Alex says, it's not where the issue is. 您可以使事件处理程序无效,但是在更改其所有者之后无论如何都将对其进行更改-超级整洁没有错,但是就像Alex所说的,这不是问题所在。

Adi's source class will allow listening objects to be collected when it itself is collected, there is no doubt. 毫无疑问,Adi的源类将允许在收集监听对象时对其进行收集。 So the problem is that Adi's source object is being kept open, possibly from some long chain of references in his customer's code. 因此,问题在于,Adi的源对象可能一直保持打开状态,这可能来自其客户代码中的一些长引用。

The following blog post also looks at a solution that Adi is decribing and explains why it's unnecessary. 以下博客文章还介绍了Adi正在描述的解决方案,并解释了为什么没有必要。

http://weblogs.sqlteam.com/mladenp/archive/2007/10/24/C-Care-about-Event-Memory-Leaks-with-Delegate.GetInvocationList.aspx http://weblogs.sqlteam.com/mladenp/archive/2007/10/24/C-Care-about-Event-Memory-Leaks-with-Delegate.GetInvocationList.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM