是否有正确的方法来取消订阅事件处理程序以使订阅者有资格获得GC?

时间:2012-01-25 18:32:52

标签: .net silverlight memory-leaks event-handling garbage-collection

我有一个发布者和订阅者。订户从发布者订阅自己。 我需要确保当订阅者超出范围时,应该取消订阅该活动,才有资格获得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的引用1}}并且不是GCed。

在我的情况下,我无法更改CreateSession方法,也无法控制订阅者的构建/销毁,我确实希望我实现Session以便一旦它超出范围应该取消订阅Service

(我的具体情况是我正在使用带有Prism和MVVM的Silverlight,Prism控制着作为订阅者的ViewModel的生命周期,但我认为这不重要,我想让我的VM意识到Prism没有不再需要它了。

有没有办法让订阅者知道超出范围,让它有机会取消订阅和GCed?

1 个答案:

答案 0 :(得分:0)

这是一个很好的方法:

LeakEvent -> WeakEvent