首页 > 解决方案 > WeakEvent 的事件监听器可以随时被垃圾回收删除吗?

问题描述

我正在寻找一种在使用事件时避免内存泄漏的解决方案(如果从未从事件源中删除侦听器,则可能会发生这种情况。我发现这篇代码项目文章描述了这样的WeakEvent类:

sealed class EventWrapper
{
    SourceObject eventSource;
    WeakReference wr;
    public EventWrapper(SourceObject eventSource,
                        ListenerObject obj) {
        this.eventSource = eventSource;
        this.wr = new WeakReference(obj);
        eventSource.Event += OnEvent;
   }
   void OnEvent(object sender, EventArgs e)
   {
        ListenerObject obj = (ListenerObject)wr.Target;
        if (obj != null)
            obj.OnEvent(sender, e);
        else
            Deregister();
    }
    public void Deregister()
    {
        eventSource.Event -= OnEvent;
    }
}

据我了解,侦听器对象包含在 aWeakReference中,从垃圾收集器的角度来看,它不被视为对事件侦听器的引用。

我的问题:使用此模式时,ListenerObject obj尽管事件源事先没有触发任何事件,但垃圾收集器是否可能会删除?在这种情况下,整个模式变得不确定,因为触发的事件没有转发到ListenerObject,因为垃圾收集器删除了它(因为只有一个WeakReference指向它)。如果这是正确的,我为什么要使用这样的模式呢?

谢谢

标签: c#weak-references

解决方案


是的,如果WeakReference是唯一拥有对 的引用的东西ListenerObject,那么ListenerObject可以在任何时候进行 GC 处理。

如果您的EventWrapper不是唯一引用 的东西ListenerObject,但您EventWrapper不知道其他东西何时会释放对ListenerObject.

例如,ListenerObject可能是出现在屏幕上的 UI 控件,并且EventWrapper可能由单例服务拥有。只要显示该屏幕,UI 控件就会保持活动状态,但会在用户更改屏幕时释放。该服务可能不知道何时发生。使用弱事件模式意味着在这种情况下您不会意外导致内存泄漏。


请注意,如果您确实想实现弱事件模式,请使用本文WeakEventManager中详述的a 。


推荐阅读