Надлежащий способ отписаться от обработчиков событий, чтобы подписчик имел право на GC? - PullRequest
0 голосов
/ 25 января 2012

У меня есть издатель и подписчик. подписчик подписывается от издателя. Мне нужно убедиться, что, когда подписчик выходит из области действия, он должен отписаться от этого события, чтобы иметь право на GC.

Вот базовый сценарий:

class Service
{
  public event Action PrintMessage;
  public void RaisePrintMessage()
  {
    if (PrintMessage != null) PrintMessage();
  }
}

class Session
{
  public Session(Service service)
  {
    _service = service;
    _service.PrintMessage += _service_PrintMessage;
  }

  void _service_PrintMessage()
  {
    Console.WriteLine("Hello world");
  }

  private readonly Service _service;
  public Service Service
  {
    get
    {
      return _service;
    }
  }

  ~Session()
  {
    Console.WriteLine("Session finalized.");
  }
}

class Program
{
  static void Main(string[] args)
  {
    var service = new Service();
    CreateSession(service);
    service.RaisePrintMessage();

    Console.ReadKey();
  }

  private static void CreateSession(Service service)
  {
    var session = new Session(service);
  }
}

Выход, как вы можете ожидать, равен Hello world (а не Session finalized.), поскольку после подписки подписчика во время Create Session, Service теперь получает ссылку на этот Session и не является GCed.

В моем случае я не могу изменить метод CreateSession, и при этом я не могу контролировать создание / уничтожение подписчика, я хочу убедиться, что я внедрил Session так, чтобы он вышел из области видимости. следует отписаться от Service.

(В моем конкретном случае я использую Silverlight с Prism и MVVM, Prism контролирует время жизни ViewModel, который является подписчиком, но я не думаю, что это имеет значение, я хочу, чтобы моя виртуальная машина знала, что Prism не больше не нужно)

Можно ли как-то уведомить подписчика о выходе из области действия, предоставив ему возможность отказаться от подписки и GCed?

1 Ответ

0 голосов
/ 02 февраля 2012

Вот хороший способ сделать это:

LeakEvent -> WeakEvent

...