.Net中ObservableCollections的MemoryManagement

时间:2014-08-17 18:51:02

标签: c# wpf garbage-collection observablecollection

我正在开发一个WPF应用程序,我正在使用一个ObservableCollection of CustomObject

public ObservableCollection<ProjectsToShow> Projects{get;set;}

ProjectsToShow类的定义

public class ProjectsToShow 
{
    public ProjectsToShow()
    {
        Wells = new ObservableCollection<WellsToShow>();
    }

    public Project ProjectObject { get; set; }

    ObservableCollection<WellsToShow> _wells;

    public ObservableCollection<WellsToShow> Wells{get;set;}
}

此类初始化WellsToShow的集合,其定义为

 public class WellsToShow 
{
    public WellsToShow()
    {
        Datasets = new ObservableCollection<DatasetsToShow>();
    }

    public Well WellObject { get; set; }

    ObservableCollection<DatasetsToShow> _datasets;
    public ObservableCollection<DatasetsToShow> Datasets
    {
        get { return _datasets; }
        set
        {
            _datasets = value;
            NotifyPropertyChanged("Datasets");
        }
    }
}

还有一个这样的等级。

现在我正在使用内存分析器分析我的应用程序,并且它不断将集合中的对象添加到内存中。我期待着打电话

Projects.Clear();

将从内存中释放所有对象,但它不会那样工作。即使我尝试将项目设置为null,但即使这样也不起作用。 WellsToShow和DatasetToShow的对象仍然保留在内存中。因此,出于测试目的,我尝试使用此代码

foreach(var project in MainViewModel.Projects)
        {
            foreach(var well in project.Wells)
            {
                well.Datasets.Clear();                    
            }
            project.Wells.Clear();
        }
        MainViewModel.Projects.Clear();

根据内存分析器,它们不再存在于内存中。为了记录,每次运行探查器时,它首先运行GC.Collect,然后进行分析。

有些人可以解释这件事是如何运作的。如果这是清除集合的正确方法,那么我需要在所有项目中运行并修复此事。

更新1,将此集合绑定到视图

我将Project属性绑定到TreeView控件并调查它的分析器。这个控件保留了我的收藏,我相信清除项目源集合应该可以完成这项工作,但事实并非如此。

  <TreeView VirtualizingStackPanel.IsVirtualizing="False"                                      ItemsSource="{Binding Projects}">
           <TreeView.Resources>
                                <HierarchicalDataTemplate DataType="{x:Type bll:ProjectsToShow}" ItemsSource="{Binding Wells}">
                                    <TextBlock HorizontalAlignment="Stretch" Text="{Binding ProjectName}" x:Name="TextBlockProject" Tag="{Binding DataContext,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}">
                                        <TextBlock.ContextMenu>
                                            <ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"  >
                                                <MenuItem 
                                                          Command="{Binding FileEditProjectCommand}">
                                                    <MenuItem.Header>
                                                        <TextBlock Text="{DynamicResource EditProject}"/>
                                                    </MenuItem.Header>
                                                </MenuItem>

                                                <MenuItem Command="{Binding FileDeleteProjectCommand}">
                                                    <MenuItem.Header>
                                                        <TextBlock Text="{DynamicResource DeleteProject}"/>
                                                    </MenuItem.Header>
                                                </MenuItem>
                                            </ContextMenu>
                                        </TextBlock.ContextMenu>
                                    </TextBlock>
                                </HierarchicalDataTemplate>
                                <HierarchicalDataTemplate DataType="{x:Type bll:WellsToShow}" ItemsSource="{Binding Datasets}">
                                    <TextBlock HorizontalAlignment="Stretch" Text="{Binding WellName}" Tag="{Binding DataContext,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}">
                                        <TextBlock.ContextMenu>
                                            <ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                                                <MenuItem Command="{Binding FileEditWellCommand}">
                                                    <MenuItem.Header>
                                                        <TextBlock Text="{DynamicResource EditWell}"/>
                                                    </MenuItem.Header>
                                                </MenuItem>
                                                <MenuItem  Command="{Binding FileDeleteWellCommand}">
                                                    <MenuItem.Header>
                                                        <TextBlock Text="{DynamicResource DeleteWell}"></TextBlock>
                                                    </MenuItem.Header>
                                                </MenuItem>
                                            </ContextMenu>
                                        </TextBlock.ContextMenu>
                                    </TextBlock>
                                </HierarchicalDataTemplate>

更新2个附加截图

enter image description here

1 个答案:

答案 0 :(得分:1)

如果视觉对象对应于集合中的对象,则这些可视对象将保留在其各自的DataContexts中的那些引用。确保仅在对象直观清除后才运行内存配置文件。

我还建议Snoop用于任何WPF调试工作,因为这可能会显示您的对象以及引用它们的内容。