1

いくつかのイベントを公開する静的クラスがあります。ですから、私には、このイベントを購読する、さまざまなライフタイムを持つさまざまな小さなクラスがあります。

私は今、これが、より長生きするイベントをサブスクライブしたときにサブスクライブしているクラスが生きたままであるために、メモリ「リーク」につながることを発見しました。私はこれがmemoryprofilerを使用して発生していることを知っており、この問題について読みました。

リストに何百もの「クライアント」が含まれている可能性があるため、手動で登録を解除することはできません。このリストはクリアされます。だから私は手で退会することはできません(そしてしたく​​ありません)。

ここでは「弱いイベントパターン」が役立つかもしれないと読みました。誰かが私をこれを実装するための「簡単な」方法に導いてくれませんか?これまで私が見つけたのは、実際に使用するには単純すぎるか、最初は理解するには複雑すぎるかのどちらかです。

または、この場合の「ベストプラクティス」はありますか?

前もって感謝します!

更新: jblの回答に基づいて、可能な解決策としてこれ(http://blogs.msdn.com/b/greg_schechter/archive/2004/05/27/143605.aspx)を見つけました。ここにコメントはありますか?それはかなり古い(2004)ので、そこにもっと良い解決策があるかもしれませんか?

4

2 に答える 2

1

そのようなものを実装したことはありませんが、私は試してみます(静的クラスまたはシングルトンを選択してください):

  • 静的クラスに、クライアントイベントハンドラーへのWeakReferenceの静的コレクションを維持させる
  • クライアントはイベントに直接サブスクライブしません。静的クラスは、弱参照コレクションからハンドラーを追加/削除するサブスクライブおよびアンサブスクライブメソッドを公開します
  • 静的クラスは、イベントに直接サブスクライブする唯一のクラスです
  • イベントがトリガーされると、静的クラスは弱参照コレクションを列挙し、まだ生きている参照のハンドラーを実行します(nullのものを削除します)

これがお役に立てば幸いです

于 2012-11-23T12:24:11.317 に答える
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 に答える