假设我有两个类,它们都不是GUI组件。A类是一个短暂的对象,它注册了一个由长期存在的B对象声明的事件。例如:
public A(B b)
{
b.ChangeEvent += OnChangeEvent;
}
如果A从未取消注册B的事件,那么A永远不会被垃圾回收吗?A需要一个Dispose方法来取消注册B的事件吗?
还有一个相关的第二个问题。如果A和B都应该在应用程序的整个执行时间内存在,那么A需要取消注册吗?
关于第一个问题:是的,B有一个对A的引用。这样A就会和B一样长寿。如果你在UI应用程序中像注册App.OnIdle事件一样注册了事件,那么这是一种很好的释放内存的方式。
至于第二个问题:最终所有东西都会被销毁。
如果需要在长期发布者的生命周期内清理已弃用的短寿订阅者的事件,则可以通过如果发布和订阅类合作的方式来实现。例如,事件订阅者的公共接口可以是一个包装器对象,该对象持有对实际事件订阅者的引用,而订阅者本身不持有对该公共对象的强引用。在这种情况下,事件订阅将不会阻止公共对象从作用域中消失并成为可供终结的对象。公共对象中的终结器可以通知订阅对象不再需要订阅,并且应该取消订阅。由于这样的通知是异步到达的,因此发布订阅的对象必须提供一种方法,以便订阅者可以异步取消订阅。这可以通过普通的“取消订阅”请求来完成,前提是发布事件保证它是非阻塞和线程安全的;不幸的是,大多数事件都没有这样的保证。
B
的生命周期内可以创建无限数量的A
,则未能断开事件将导致无限制的内存泄漏。如果A
在其有用寿命期间需要B
发布的事件,则A
应该实现IDisposable
并在其Dispose
方法中断开与B
的事件连接。 - supercat