14

Prism アプリケーションでメモリ リークを引き起こす MEF のパーツ ライフタイムで問題が発生しました。

PartCreationPolicy私のアプリケーションは、に設定されているビューとビューモデルをエクスポートしますCreationPolicy.NonSharedViewBaseビューとビューモデルはそれぞれとを継承しViewModelBase、 を実装しIDisposableます。

現在、私のパーツは を実装IDisposableしているため、それらへの参照はコンテナーによって保持されているため、ガベージ コレクターによって解放されません。部品の寿命に関する MEF のドキュメントによると、これは設計によるものです。

コンテナーは、次のいずれかに該当しない限り、作成したパーツへの参照を保持しません。

  • パーツは次のようにマークされますShared
  • 部分は実装しますIDisposable
  • 再構成を許可するように 1 つ以上のインポートが構成されています

では、MEF がこれらのパーツへの参照を保持しないようにするにはどうすればよいでしょうか。MEF が実装されていても、自分のパーツへの参照を保持したくないことを MEF に知らせるために使用できる属性はありますIDisposableか?

上記の記事で説明した両方の戦略は、私にとって良い解決策とは思えません。

  • ReleaseExportパラメータとしてオブジェクトが必要ですがExport、提供方法がわかりません。ビューのインスタンスはありますが、ビューの作成に使用されたコントラクトを知る方法がありません。ReleaseExportコンテナーによって作成された任意のオブジェクトを受け取ることができるオーバーロードがあれば、それは素晴らしいことです。
  • 子コンテナーを使用することも、自然な選択肢のようには思えません。

どんな助けでも大歓迎です。

4

4 に答える 4

8

Prismがビューオブジェクトのある種の有効期間をサポートしていない限りIDisposable、ビューによって公開されているインターフェイスのリストから削除する以外に、ここで解決策はありません。

この問題を処理するための3つのMEFアプローチがあり、すべて他のレスポンダーによって言及されています。

  • ExportFactory<T>
  • 子コンテナ
  • ReleaseExport()

それらはすべて、元のエクスポートを要求するコードの一部(この場合はPrism内のコード)でいくつかの作業を必要とします。オブジェクトを消費するコードが、オブジェクトがいつどのように作成されたかを認識しなければならないことは望ましくないため、これはある程度意味があります。

ReleaseExportedObject()複数の(たとえばプロパティ)エクスポートは同じ値を返す可能性があるため、MEFにはありません。論理的に提供することは可能かもしれませんが、複雑さが増すため、近い将来、MEFが対処する可能性は低くなります。

お役に立てれば; Prismコミュニティの他の人がこれに遭遇し、アドバイスを提供できると確信しているので、この質問「prism」のタグを付け直しました。

于 2012-01-09T18:52:12.280 に答える
5

実装するときIDisposableは、型を決定論的な方法でクリーンアップする必要があると言っているようなものです (IDisposable.Disposeガベージ コレクターが時間であると判断したときに、ランダムではなく呼び出すことによって)。

あなたの場合、おそらくやりたいことではないコンテナを破棄するときにのみ、ビューモデルが破棄されます。これを回避するには、次の 2 つの解決策が考えられます。

  • IDisposableビュー モデルには実装しないでください。とにかくいつクリーンアップされるかは気にしないようですが、なぜそれらを作成するのIDisposableですか?

  • コンテナーに非共有の各ビュー モデルを作成させる代わりに、共有ビュー モデル ファクトリ クラスを使用できます。次に、そのクラスをビュー モデルの所有者に挿入して、所有者が明示的にビュー モデルを作成できるようにすることができます。おそらく、これらの所有者は、ビュー モデルを破棄するタイミングも知っているでしょう。

基本的に、何かが使い捨てである場合、それは、使い捨てのものを処分する必要があるコード内の賢明なポイントである必要があります。

于 2012-01-09T13:53:38.687 に答える
4

これらのインスタンスは、インポートされたExportFactory<T>を介して作成する必要があります。次に、を介してそれらを破棄するために必要な制御ができますExportLifetimeContext<T>.Dispose()

ただし、これは、次の.NETバージョン(4.5)またはcodeplexの最新のMEFプレビューリリースでのみ使用できます。(古いバージョンのMEFでは、同じ機能がサンプルとして実装され、このブログ投稿で説明されているように、 PartCreatorと呼ばれていました。)

于 2012-01-09T13:57:59.987 に答える