减少内存占用

时间:2012-02-23 11:14:14

标签: c# wpf silverlight linq

我有主流(IEnumerable),超过100,000件商品。然后我控制了多个AutoCompleteBox。所有这些AutoCompleteBox都绑定到主流。

首先

现在问题是我的控件中有大约10个AutoCompleteBox,并且所有主流都是他们的ItemsSource,从而导致大量内存占用。

第二

我还需要在运行时根据某些事件在少数AutoCompleteBox的ItemsSource上应用过滤器。

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

2 个答案:

答案 0 :(得分:0)

内存占用

我认为这不仅取决于您的代码实现,还取决于AutocompleteControlas,它如何使用绑定数据源。

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

  • 对于WPF4,请查看是否使用WPF Data Virtualization进行AutocompleteControl。基本上,您可以重新定义标准项面板以使用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");
      }
   }
}

答案 1 :(得分:0)

对于数据收集的内存占用,您应该查找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; }
    }