我编写了一个Outlook加载项(OL2010)。它在功能区栏上有一个菜单,上面有各种图标,可以打开新窗口(希望不是太深入;))。下面是其中一个图标Click
处理程序的示例。
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,并且当我关闭视图时,再次没有释放。
我认为这是因为我每次都在创建一个新的视图模型,所以我添加了一些代码来检查它是否已经实例化(视图和视图模型现在在类级别注册,而不是在方法中注册,所以我不是每次都创建一个新的) - _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;
}
内存仍然分配。如何正确处理对象(或者我应该以不同的方式实例化它们),这样每次打开它们时都不会消耗另一块内存?
由于
米克
答案 0 :(得分:1)
检查VM是否为空是一个好主意,但是通过在关闭处理程序中将其设置为null,它变得无用:) 您可以尝试使视图成为包含类中的字段而不是局部变量。这样,您不需要每次都创建新视图。
至于内存使用情况,在我看来你做得对。由于GC仅在必要时收集,因此需要一些时间直到内存消耗下降。