3

Outlook アドイン (OL2010) を作成しました。リボン バーには、さまざまなアイコンを含むメニューがあり、さまざまな操作を実行する新しいウィンドウが開きます (詳細ではないことを願っています ;))。Clickアイコンハンドラーの 1 つの例を以下に示します。

public void OnViewMyTracksClick(Office.IRibbonControl control)
{
    try {
    MyTracksViewModel viewModel = new MyTracksViewModel();
    MyTracksView view = new MyTracksView();
    view.DataContext = viewModel;
    view.Show();
    }
    catch (Exception ex)
    {
        Log.Error("xxxxx", "Error on button click: " + ex.Message + Environment.NewLine + ex.InnerException);
    }
}

Outlook でボタンをクリックしてこのビューを開くと、メモリ使用量がOutlook.exe10 MB 増加することがわかります (ウィンドウとそれに付随するデータ)。ビューを閉じると、そのメモリは再利用されません。ボタンをもう一度クリックすると、さらに 10 MB が追加され、ビューを閉じても何も解放されません。

これは、毎回新しいビューモデルを作成しているためだと思ったので、既にインスタンス化されているかどうかを確認するコードを追加しました (ビューとビューモデルは、メソッド内ではなく、クラス レベルで登録されるようになりました。毎回新しいものを作成しないでください) -_allTracksVMのインスタンス化ですAllTracksViewModel_allTracksVビューです。

public void OnViewAllTracksClick(Office.IRibbonControl control)
{
    try {
        if (_allTracksVM == null)
        {
            _allTracksVM = new AllTracksViewModel();

        }
        _allTracksV = new AllTracksView();
        _allTracksV.DataContext = _allTracksVM;
        _allTracksV.Show();
    }
    catch (Exception ex)
    {
        Log.Error("xxxxx", "Error on button click: " + ex.Message + Environment.NewLine + ex.InnerException);
    }
}

これは違いがないように見えました。EventHandler次に、ビューが閉じられたときに起動する を追加しました。

_allTracksV.Closing += new System.ComponentModel.CancelEventHandler(this.view_RequestClose);

これにより、両方のオブジェクトが null に設定されます (この時点で、ストローをつかんでいることがわかります)。

void view_RequestClose(object sender, EventArgs e)
{
    _allTracksVM = null;
    _allTracksV = null;
}

メモリは割り当てられたままです。オブジェクトを開くたびにメモリの別のチャンクを消費しないように、オブジェクトを正しく破棄するにはどうすればよいですか (または、おそらく別の方法でインスタンス化する必要があります)。

ありがとう

ミック

4

1 に答える 1

0

VM の Null をチェックするのは良い考えでしたが、クローズ ハンドラで null に設定すると、役に立たなくなります :) ビューを、ローカル変数ではなく、含まれるクラスのフィールドにすることができます。そうすれば、毎回新しいビューを作成する必要はありません。

メモリ使用量に関しては、あなたが正しくやっているようです。GC は必要な場合にのみ収集するため、メモリ使用量が減少するまでには時間がかかります。

于 2012-11-01T11:50:34.610 に答える