2012-05-07 11 views
1

私たちのWPF/MVVMアプリケーションで何らかのメモリリークを追跡しようとしていて、何かが発生しました...MVVMでは、ViewModelでモデル項目のイベントをフックするとメモリリークが発生しますか?

関連するViewModelでModelItemイベントをインスタンス固有のハンドラでリッスンすると、 ModelItemがまだ存在する限り、ViewModelItemはハングアップしますか?

が、これは漏れを起こした場合、あなたはそれをどのように/どこ外すん

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アーキテクチャには足りないので、ここで何をすべきか分かりません。

答えて

1

はい、それはリークが発生します。..またはより具体的にビューがもはやModelItemItemViewModel

への参照を保持しているので、あなたがDisposeを実装しているのEventHandlerを外すことができ、表示されたときItemViewModelが収集されませんされません。 ViewModelのライフサイクルを制御できる場合は完全に有効です。問題は、どのコンポーネントがItemViewModelを作成しているかです。それが別のビューモデルであれば、それにdisposeを委譲できます。ビューがビューモデルを作成する場合は、Disposeメソッドを呼び出すことができます。

ただし、MVVMLightツールキットのように使用する場合は、その代わりにICleanupインターフェイスを使用できます。詳細はanswerをご覧ください。

+0

私たちのItemViewModelクラスはルートControlViewModelで管理されています(ListBoxViewModelはModelItemのリストにバインドされたListItemViewModelsを管理します)。ルートVMがUIでアンロードするタイミングを制御できるので、すべての子ViewModelItemオブジェクトのイベントリスナー。 (GCパターンがrefカウントよりもメモリのほうが優れているので、別の問題を1つ置き換えました!) – MarqueIV

+0

GCは管理対象リソース用です。パブリッシャとサブスクライバの両方が収集を開始していない限り、明示的にアンフックする必要があるため、イベントハンドラは_managed_ではないと主張できます。 – aqwert

2

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

決定的なデタッチを必要としないデリゲートへの弱い参照を実装します。

+0

これは私たち自身のロールになっているイベントの方向ですが、既存のオブジェクトのすべてのイベント(ObservableCollectionなど)に設定しなければならないというのは残念です – MarqueIV

+0

Fotrと同じ理由で、弱いイベント\弱いコマンドが必要ですMVVMの設計によって実装されています。 MVVMはイベント駆動型アーキテクチャを嫌う。それはあまりにも弱い方法でコマンド駆動アーキテクチャを奨励します。 –

+0

しかし、観測可能なコレクションのようなものを扱うとき、コマンド駆動型アーキテクチャではどのようにコマンドがありますか?モデルが変更されたときにViewModelを自動的に更新する必要がありますが、非コマンドの方法を含め、モデルを変更できる場所はいくつでもあります。 – MarqueIV

関連する問題