Может ли прослушиватель событий WeakEvent быть удален сборщиком мусора в любое время? - PullRequest
2 голосов
/ 16 января 2020

Я ищу решение, позволяющее избежать утечек памяти при использовании событий (которые могут произойти, если слушатель никогда не удаляется из источника события. Я нашел эту статью проекта кода , описывающую класс WeakEvent как this:

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;
    }
}

Насколько я понял, объект слушателя обернут в WeakReference, который не рассматривается как ссылка на прослушиватель событий с точки зрения сборщиков мусора.

Мой вопрос: возможно ли, чтобы при использовании этого шаблона сборщик мусора удалял ListenerObject obj, хотя источник события не сработал заранее? В этом случае весь шаблон становится неопределенным c, так как событие сработало не пересылается на ListenerObject, потому что сборщик мусора удалил его (потому что на него указывает только WeakReference). Если это правильно, зачем мне в любом случае использовать такой шаблон?

Thx

1 Ответ

2 голосов
/ 16 января 2020

Да, если WeakReference - единственное, что содержит ссылку на ListenerObject, тогда ListenerObject может быть G C 'd в любой точке.

Вы бы использовали шаблон вот так, если ваш EventWrapper класс не единственное, что имеет ссылку на ListenerObject, но ваш EventWrapper не знает, когда эта другая вещь выпустит свою ссылку на ListenerObject.

Например, ListenerObject может быть элементом управления пользовательского интерфейса, который появляется на экране, а EventWrapper может принадлежать одноэлементной службе. Элемент управления пользовательского интерфейса будет оставаться активным до тех пор, пока отображается этот экран, но будет освобожден, когда пользователь изменит экран. Служба может не знать, когда это произойдет. Использование шаблона слабых событий означает, что в этом случае вы случайно не получите утечку памяти.


Обратите внимание: если вы хотите реализовать шаблон слабых событий, используйте WeakEventManager в качестве подробно описано в этой статье .

...