1

WPF/MVVM アプリでいくつかのメモリ リークを追跡しようとすると、何かが発生しました...

インスタンス固有のハンドラーを使用して関連付けられた ViewModel で ModelItem イベントをリッスンすると、ModelItem がまだ存在する限り、ViewModel がハングアップすることはありませんか?

この場合を考えてみましょう...

public class ItemViewModel
{
    public ItemViewModel(ModelItem item)
    {
        this.Item = item;
        item.SomeEvent += ItemSomeEventHandler
    }

    Public ModelItem Item { get; private set; }

    // Note: This is a handler on this instance, not a shared handler
    private void ItemSomeEventHandler(object s, EventArgs e)
    {
        Console.WriteLine(“The model changed!”);
    }
}

これがリークを引き起こす場合、どのように/どこでフックを外しますか? 「Dispose」でそれを行うことはできません。何かがまだそれへの参照を持っている場合、それは呼び出されないためです。モデルアイテムのように見えます。

このViewModelが使用されているコントロールにDisposeを実装し、そこにイベントアンフックルーチンを細流化するのが適切な場所でしょうか? 自分の内部を確実にクリーンアップするために外部に依存するのは少し危険に思えますが、EventManager アーキテクチャに行くまでは、ここで何をすべきかわかりません。

4

2 に答える 2

2

WeakEvent / DelegateCommandsを使用しないのはなぜですか?

それらは、決定論的な切り離しを必要としないデリゲートへの弱い参照を実装します。

于 2012-05-07T06:39:15.613 に答える
1

はい、リークが発生します。具体的には、がへの参照を保持しているItemViewModelため、ビューが表示されなくなったときには収集されません。ModelItemItemViewModel

Disposeのライフサイクルを制御できる場合は、完全に有効なイベントハンドラーを実装してフックを解除できますViewModel。問題は、どのコンポーネントが作成しているのItemViewModelかということです。それが別のビューモデルである場合は、disposeをそれに委任できます。または、ビューがビューモデルを作成する場合は、Disposeメソッドを呼び出すことができます。

ただし、MVVMLightツールキットのように使用する場合は、代わりにそのICleanupインターフェイスまたは同様のものを使用できます。詳細については、この他の回答を確認してください。

于 2012-05-07T04:40:47.103 に答える