我編寫了一個Outlook加載項(OL2010)。它在功能區欄上有一個菜單,帶有各種圖標,可以打開新窗口來執行操作(希望不要太深入;))。下面是一個圖標Click
處理程序的示例。WPF正確處理視圖和視圖模型
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.exe
增長10MB的內存使用量(窗口和它附帶的數據)。當我關閉視圖時,沒有任何內存被回收。如果我再次點擊該按鈕,則會添加另一個10mb,並且當我關閉視圖時再次沒有任何內容被釋放。
我認爲這是因爲我每次都創建一個新的viewmodel,所以我添加了一些代碼來檢查它是否已經實例化(view和viewmodel現在在類級別註冊,而不是在方法內註冊,所以我不會每次創建一個新的) - _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);
這種設兩個對象爲空(你可能會說我在抓救命稻草在這一點上):
void view_RequestClose(object sender, EventArgs e)
{
_allTracksVM = null;
_allTracksV = null;
}
內存仍然分配。我如何正確地處理對象(或者我應該以不同的方式實例化它們),以便每次打開時都不會消耗另一塊內存?
感謝
米克
感謝您的回覆。在關閉處理程序中擺脫了null事物。我希望關閉視圖也會處理它(至少最終),但似乎並不是這樣。我的Outlook最初運行時間大約爲100MB。我可以繼續打開和關閉窗口,直到Outlook使用超過500MB。現在肯定只有一個視圖模型的實例,所以我沒有受過教育的猜測是視圖掛在消費內存上。不知道多少次垃圾收集應該發生,但2小時沒有區別。 – MJM
您是否嘗試將視圖本身變成字段?所以你不必每次都創建一個新的視圖,只是顯示和隱藏它? – MrEdge
是的,這就是我最終做的事情,似乎有一個合理的差異。內存仍然上升,但速度相當慢,現在似乎只發生在一個視圖(嵌入在預覽窗口中顯示的元素主機中)。可能有一個暫停的臨時結果集。感謝您的建議。 – MJM