【问题标题】:WPF disposing of view and viewmodel correctlyWPF 正确处理视图和视图模型
【发布时间】:2012-11-01 10:36:53
【问题描述】:

我编写了一个 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,当我再次关闭视图时,不会释放任何内容。

我认为这是因为我每次都在创建一个新的视图模型,所以我添加了一些代码来检查它是否已经实例化(视图和视图模型现在在类级别注册,而不是在方法中,所以我不会每次都创建一个新的)-_allTracksVMAllTracksViewModel 的实例化。 _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;
}

内存仍然分配。如何正确处理对象(或者我应该以不同的方式实例化它们),以便它们每次打开时都不会消耗另一块内存?

谢谢

米克

【问题讨论】:

    标签: c# wpf mvvm


    【解决方案1】:

    检查虚拟机是否为 Null 是个好主意,但通过在关闭处理程序中将其设置为 null,它会变得无用 :) 您可以尝试使视图成为包含类中的字段而不是局部变量。这样您就不需要每次都创建一个新视图。

    至于内存使用,在我看来你做得对。由于 GC 只在必要时进行收集,因此内存使用量下降需要一些时间。

    【讨论】:

    • 感谢您的回复。摆脱了关闭处理程序中的 null 事物。我希望关闭视图也会处理它(至少最终),但似乎没有。我的 Outlook 最初运行大约 100mb。我可以继续打开和关闭窗口,直到 Outlook 使用超过 500mb。现在肯定只有一个视图模型实例,所以我没有受过教育的猜测是视图在消耗内存。不知道应该多久进行一次垃圾收集,但 2 小时没有区别。
    • 您是否尝试让视图本身成为一个字段?这样就不必每次都创建新视图,只需显示和隐藏即可?
    • 是的,这就是我最终所做的,它似乎产生了相当大的差异。内存仍然会增加,但速度要慢得多,现在似乎只发生在一个视图中(嵌入在预览窗口中显示的元素宿主中)。可能有一个临时的结果集。感谢您的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    • 2018-08-14
    • 2017-08-17
    相关资源
    最近更新 更多