垃圾收集器和事件处理程序

本文关键字:事件处理 程序 收集器 | 更新日期: 2023-09-27 18:02:35

一个简短的问题。假设我有一个实现如下例中的类。

class Subscriber
{
    private Publisher publisher = new Publisher;

    public Subscriber()
    {
       publisher.SomeEvent += new EventHandler(OnEventFired);
    }
    private void OnEventFired(object sender, EventArgs e)
    {
    }
}

在程序的某个地方,我有一个方法看起来像这样:

public void DoSomething()
{
    Subscriber subscriber = new Subscriber();
}

我是否认为这会导致内存泄漏,因为订阅者从未取消订阅发布者事件,从而导致它们都保持对彼此的强引用?

垃圾收集器和事件处理程序

这不会导致泄漏 - GC可以处理循环引用,没有问题。

然而,这将意味着发布者将有效地拥有对订阅者的引用,因此订阅者无法被垃圾收集,直到发布者符合GC条件,或者它从事件中取消订阅。

如果在事件发布者的GC生命周期内,可能会产生任意数量的事件订阅者并在未取消订阅的情况下被放弃,那么这种悬空订阅将构成内存泄漏。如果事件发布者在放弃订阅者的时候有资格进行垃圾收集,或者在最坏的情况下,每个发布者可以创建和放弃有限数量的订阅者,则不存在内存泄漏。

我对。net的不满之一是微软不支持事件清理。这在vb.net中尤其令人讨厌,它确保更改"WithEvents"变量将正确地生成适当的订阅和取消订阅,但没有提供方便的方法让IDisposable处理程序取消订阅对象持有的所有事件。