自动订阅活动

时间:2012-11-23 12:10:00

标签: c# events memory-leaks event-handling

我有一个静态类,它发布了一些事件。所以我有许多不同的小班,他们有不同的生命期订阅这个活动。

我现在发现这导致记忆“泄漏”,因为订阅类在订阅更长寿的事件时仍然活着。我知道这是通过使用memoryprofiler发生的,我读到了这个问题。

我无法手动取消订阅,因为我可能在列表中有数百个“客户”。此列表将被清除。所以我不能(也不想)手工取消订阅。

我读到“弱事件模式”可能对此有所帮助。有人可以请我以“简单”的方式实现这个吗?直到现在我发现的所有东西要么在实践中使用太简单,要么在开始时太难理解。

或者这种情况有什么“最佳做法”吗?

提前致谢!

更新 根据jbl的回答,我发现这个(http://blogs.msdn.com/b/greg_schechter/archive/2004/05/27/143605.aspx)作为一种可能的解决方案。这里有评论吗?这是相当古老的(2004年),所以可能有更好的解决方案吗?

2 个答案:

答案 0 :(得分:1)

最佳实践:当类订阅由非此类构造的对象生成的事件时,始终实现Dispose模式。

然后在Dispose方法中删除处理程序。

public NotificationServiceAccessor(ObjectWithEvent objectWithEvent)
{
    _notificationService = new NotificationService();
    _notificationService.StatusChanged += NotificationService_StatusChanged; // Local object, no Dipose

    _objectWithEvent = objectWithEvent;
    _objectWithEvent.AnEvent += AnEventHandler(); // Event that has to be disposed.
}

    #region IDisposable Members

    protected bool Disposed { get; private set; }

    private void Dispose(bool disposing)
    {
        if (!this.Disposed)
        {
            this.InternalDispose(disposing);
        }

        this.Disposed = true;
    }

    protected virtual void InternalDispose(bool disposing)
    {
        if (disposing)
        {
                        // Dispose here the event handlers
                        _objectWithEvent.AnEvent -= AnEventHandler()
        }

        // Dispose here only unmanaged objects 
        // Don’t use managed objects here because maybe 
        // they have been finalized already
    }

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~NotificationServiceAccessor()
    {
        this.Dispose(false);
    }

    #endregion

答案 1 :(得分:1)

从未实现类似的东西,但我会尝试(使用静态类或单例,您的选择):

  • 让静态类维护WeakReference到客户端事件处理程序的静态集合
  • 客户不直接订阅该活动。静态类公开了subscribe和unsubscribe方法,这些方法在弱引用集合中添加/删除处理程序
  • 静态类是唯一直接订阅事件
  • 的类
  • 在事件触发时,静态类枚举弱引用集合并为仍然存活的引用运行处理程序(删除空引用)

希望这会有所帮助

相关问题