【问题标题】:Reducing Memory Footprint减少内存占用
【发布时间】:2012-02-23 11:14:13
【问题描述】:

我有一个包含超过 100,000 个项目的 Main Stream (IEnumerable)。然后我控制了多个AutoCompleteBox。所有这些 AutoCompleteBox 都绑定到 Main Stream。

第一:

现在的问题是我的控件中有大约 10 个 AutoCompleteBox,并且都将 Main Stream 作为它们的 ItemsSource,从而导致内存占用很大。

第二:

我还需要在运行时根据某些事件对几个 AutoCompleteBox 的 ItemsSource 应用过滤器的功能。

我需要您的建议来减少这种内存占用并具有在运行时应用过滤器的功能。

【问题讨论】:

  • 1) 你在使用 MVVM 吗? 2) MainStream 是否是一个带有 getter 的属性,它根据请求/惰性 getter 返回项目列表,或者这是一次填充的字段/属性?

标签: c# wpf silverlight linq


【解决方案1】:

内存占用

我相信这不仅取决于您的代码实现,还取决于 AutocompleteControl 以及它如何使用绑定的数据源。

  • 在 getter 中使用 yield return 将 MainStream 实现为计算属性,以便在运行时按需计算/返回项目

  • 对于 WPF4,查看 AutocompleteControl 是否使用 WPF 数据虚拟化。基本上,您可以重新定义标准项目面板以使用 VirtualizingStackPanel 而不是 StackPanel,因此框架只会为可见项目分配内存并创建 UI 元素,而不是所有绑定。

动态过滤

看看 MVVM 方法。很容易使用绑定到 UI 过滤器控件的属性来计算 MainSTream 项目,基本上 getter 将使用公共绑定属性,并且每次更改这些属性时 - MainSTream 将重新计算项目并通过INotifyPropertyChanged 通知 UI,显然您需要实现支持INotifyPropertyChanged。见One sentence explanation to MVVM in WPF?

public IEnumerable<IMyItem> MainStream
{
   get
   {
      foreach(var item in mainDataSource)
      {
         if (item.Name == this.NameFilterBoundToUiTextBox)
         { 
            yield return item;
         }
      }
   }
}

private string nameFilter;
public string NameFilterBoundToUiTextBox
{
   get
   {
       return this.nameFilter;
   }
   set
   {  
      if (this.nameFilter != value)
      {
         this.nameFilter = value;

         // TODO: Implement INotifyPropertyChanged
         this.OnPropertyChanged("NameFilterBoundToUiTextBox");

         // THis would notify UI to rebind MainSream
         this.OnPropertyChanged("MainStream");
      }
   }
}

【讨论】:

    【解决方案2】:

    对于数据收集的内存占用,您应该查找Sequential Data Cache

    减少内存消耗的示例:

        public void TestAutoCompleteLookup()
        {
            var path = "";
            using (var c = SequentialDataCache<AutoCompleteItem>.Initialize())
            {
                path = c.Path;
    
                //add 100.000 items 
                for (int i = 0; i < 100000; i++)
                {
                    c.Add(new AutoCompleteItem() { Text = string.Format("{0}Text", i) });
                }
    
                //query
                var pattern = "1";
                var items = c.Where(autoCompleteItem => autoCompleteItem.Text.StartsWith(pattern)).ToArray();
    
            }
    
            if (File.Exists(path))
                File.Delete(path);
        }
    
        [Serializable]
        private class AutoCompleteItem
        {
            public string Text { get; set; }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-07
      • 2016-11-09
      • 1970-01-01
      • 1970-01-01
      • 2021-07-21
      • 2012-08-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多