C# 弱引用和事件处理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/185931/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:05:02  来源:igfitidea点击:

WeakReference and event handling

c#.netdesign-patternsweak-references

提问by Cherian

Is it a good practice to implement event handling through WeakReference if that event is the only thing holding the reference and that we would need the object to be garbage collected?

如果该事件是唯一持有引用的事件并且我们需要对对象进行垃圾回收,那么通过 WeakReference 实现事件处理是否是一个好习惯?

As an argument to this:

作为对此的论据:

Folks say that if you subscribe to something it's your responsibility to unsubscribe and you should do it.

人们说,如果您订阅了某些内容,则有责任取消订阅,您应该这样做。

回答by Samuel Kim

While what you suggest solves one set of problems (event reference management and memory leak prevention), it is likely to open up a new set of problems.

虽然您的建议解决了一组问题(事件引用管理和内存泄漏预防),但很可能会引发一系列新问题。

One problem I can see is during event handling process if the source object is garbage collected (as it was only held with a weak reference), any code that access the source object will result in null reference exception. You can argue that the event handler should either not access the source object or it must have a strong reference, but it can be argued that this could be a worse problem than the one you are trying to solve in the first place.

我可以看到的一个问题是,在事件处理过程中,如果源对象被垃圾收集(因为它只用弱引用保存),任何访问源对象的代码都将导致空引用异常。您可以争辩说事件处理程序不应该访问源对象,或者它必须具有强引用,但可以争辩说,这可能比您首先尝试解决的问题更糟糕。

回答by Ilya Ryzhenkov

Weak delegate pattern is something that should be there in CLR. Normal events exhibit "notify me while you are alive" semantics, while often we need "notify me while I'm alive". Just having delegate on WeakReference is wrong, because delegate is an object too and even when recepient is still alive and have incoming references, delegate itself is only being referenced by said WeakReference and will be collected instantly. See this old postfor an example of implementation.

弱委托模式是 CLR 中应该存在的东西。正常事件表现出“在你活着时通知我”语义,而我们通常需要“在我活着时通知我”。仅仅在 WeakReference 上使用委托是错误的,因为委托也是一个对象,即使当接收者还活着并且有传入的引用时,委托本身也只会被所说的 WeakReference 引用,并且会立即被收集。有关实现的示例,请参阅此旧帖子

回答by Glenn Block

Weak references in their own right, don't solve the problem as the delegate holds the reference. In the Composite Application Library which ships with Prism (www.microsoft.com/compositewpf) there is a WeakDelegate class that you could pull from the source. The WeakDelegate basically ues reflection and creates a delegate only for a moment in time and then releases it, thereby no holding any pointers. Within CAL it is used by the EventAggregator class, but you are free to rip it out for your own usage as it is under MS-PL.

弱引用本身就不能解决问题,因为委托持有引用。在 Prism (www.microsoft.com/compositewpf) 附带的复合应用程序库中,有一个可以从源中提取的 WeakDelegate 类。WeakDelegate 基本上使用反射,只在一段时间内创建一个委托,然后释放它,因此不持有任何指针。在 CAL 中,它由 EventAggregator 类使用,但您可以随意将其撕掉以供您自己使用,因为它在 MS-PL 下。

回答by Ed Ball

It is good to get in the habit of unsubscribing from events when you can, but sometimes there isn't an obvious "cleanup" method where it can be done. We recently posted a blog articleon this subject; it includes methods that make it easy to subscribe to an event with a WeakReference.

养成尽可能取消订阅事件的习惯是件好事,但有时没有明显的“清理”方法可以完成。我们最近发布了一篇关于这个主题的博客文章;它包括使订阅具有 WeakReference 的事件变得容易的方法。