当“标签”从“项目”集合中删除时,内存会发生什么变化?

时间:2019-04-10 13:19:57

标签: c# wpf memory-management

我将在这个问题中使用伪代码,因此,请在理论方面进行参考(我的意思是,将进行一些简化)

假设这种情况:

我的应用程序具有 MainWindow ,该应用程序具有 TabControl 。为了从其集合中删除项目,我使用了 MainWindow static 功能,如下所示:

public static void CloseTab(string someKindOfTabIdentity)
{
    var tab = myTabControl.Items.FirstOfDefault(someScenario);
    if (tab != null)
    {
        myTabControl.Items.Remove(tab);
        tab.Content = null;
        tab = null;
        GC.Collect();
    }
}

现在,我有 Page1 ,我可以在其中允许用户通过某些功能关闭标签页

private void GoToPage2()
{
    MainWindow.CreatePage2AddToTabControlAndNavigateToIt()
    MainWindow.CloseTab(myCurrentPage1Tab);
    App.Cursor = Cursors.Arrow;
}

此功能应创建新的选项卡,为其分配内容,然后使用MainWindow.CloseTab(myCurrentPage1Tab);关闭包含 Page1 的当前选项卡。

以下是问题:

  1. MainWindow.CloseTab(myCurrentPage1Tab);行之后 Page1 的内存分配会发生什么?

  2. 如果MainWindow.CloseTab(myCurrentPage1Tab);行后有代码, Page1 的内存分配会怎样?

  3. 何时要从内存中完全释放 Page1

  4. 是否有更好(更有效)的方法来实现这一目标?

这种简化的情况一直是我的WPF应用程序所发生的事情,我担心这是否是一种管理选项卡项和应用程序内存的安全方法。

2 个答案:

答案 0 :(得分:1)

  1. Page1的实例将有资格进行垃圾回收,前提是尚无任何其他活动对象引用该实例。
  2. 没有什么要紧的,除非“ MainWindow.CloseTab(myCurrentPage1Tab);行之后的代码”对Page1引用执行了某些操作,从而阻止了实例的收集。
  3. 垃圾收集器收集后。这种情况何时发生是不确定的,即您真的不知道什么时候发生,因此您不必在意。
  4. 好吧,没有理由显式调用GC.Collect。这几乎总是一个坏主意。假设Page1的实例在您的应用程序中不再被引用,无论如何它最终都会被收集。另外,我不知道您为什么使用静态方法,但我想那是另一回事了。

总而言之,您应该简单地确保代码中没有任何引用使页面的生存期比必要的更长,但又远离垃圾收集器。

答案 1 :(得分:0)

1-3

当垃圾回收器这样做时,它将从内存中删除未引用的控件。确切的时间取决于您的应用程序在做什么。

当收集器清除某些控件时,通常并不重要。如果对您有用,那么您可能在设计中遇到了问题。

4

取决于您在做什么。几乎所有开发团队都将mvvm与wpf一起使用。通常的方法是将视图模型的集合绑定到该tabcontrol的itemssource上,并将其模板化为tab。删除标签将涉及从该列表中删除视图模型。

通过这种方法,只有当前选项卡可以模板化到UI中。

您的描述使此声音听起来像是导航。用于mvvm样式导航的常见模式是首先使用viewmodel(您应该能够搜索大量示例)。从本质上讲,这将涉及从窗口视图模型公开一个属性,该属性将保存当前视图的视图模型。那将绑定到contentcontrol的内容,并根据数据类型将其模板化到UI中。