1

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

我现在发现这会导致内存“泄漏”,因为订阅类在订阅一个更长寿的事件时仍然存在。我知道这是通过使用内存分析器发生的,并且我读到了这个问题。

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

我读到“弱事件模式”在这里可能会有所帮助。有人可以引导我采用一种“简单”的方式来实现这一点吗?到目前为止,我发现的所有内容要么太简单而无法在实践中使用,要么太复杂而无法在一开始就理解。

或者这种情况有什么“最佳实践”吗?

提前致谢!

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

4

2 回答 2

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
于 2012-11-23T12:13:00.637 回答
1

从来没有实现过这样的东西,但我会尝试(使用静态类或单例,你的选择):

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

希望这会有所帮助

于 2012-11-23T12:24:11.317 回答