.net - 集合内存不足

标签 .net collections out-of-memory

我使用的是 .NET 4.0,因此有 2 GB 的限制

此 get 大约有 1/2 的时间抛出内存不足异常

public IEnumerable<FTSword7bitThesaurus> FTSwordsPlusSelected
{
    get
    {
        try
        {
            return FTSWords7bit.Select(w => new FTSword7bitThesaurus(this, w, selectedKeys.Contains(w.Key)));
        }

堆栈跟踪开始:
System.Collections.Generic.List'1_setCapacity(int32值)

这是调用 get 的代码

<ListView Grid.Row="4" Grid.Column="1" x:Name="lvFTSWordsMine"
                              ItemsSource="{Binding ElementName=lvThesarus, Path=SelectedItem.FTSwordsPlusSelected, Mode=OneWay}"
                              ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Hidden" VerticalContentAlignment="Stretch">

但令我困惑的是 FTSwordsPlusSelected (应该)小于 FTSWords7bit

这是FTSword7bitThesaurus中唯一的数据
一个 bool 值和两个引用

public class FTSword7bitThesaurus : INotifyPropertyChanged
{
    bool selected = false;
    FTSword7bit fTSword;
    FTSthersarus fTSthersarus;

FTSWord7bit 平均有 20 个字节的数据
FTSWords7bit 集合大小为 1200 万 FTSWord7bit
该集合(尚未)抛出内存不足异常

我在收集我认为应该较小的对象时内存不足
我无法分析整个集合,因为分析器犹豫不决

selectedKeys 只是一个 HashSet,永远不会超过 10,000 个,通常少于 200

既然显然 FTSWords7bit 是首先创建的,您认为这只是由于内存碎片吗?

关于如何避免内存不足问题有什么想法吗?

FTSWords7bit 被广泛使用,我一直坚持使用
FTSword7bitThesaurus 仅由一个管理屏幕使用,我希望当他们退出该屏幕时将其丢弃
大多数时候收集的数据少于 100 万,但这是一个奇怪的数据集
如果我能稳住1200万就OK
我们甚至可以忍受 1/2 时间内存不足的情况,但这并不能增强用户的信心
距离 .NET 4.5 还需要几个月的时间

来自已接受的答案
修复方法只是分页
问题很可能是连续的内存块不可用

public void NextPage()
{
    page++;
    NotifyPropertyChanged("FTSwordsPlusSelected");
}

public IEnumerable<FTSword7bitThesaurus> FTSwordsPlusSelected
{
    get
    {
        try
        {
            return FTSWords7bit.Skip(page * pageSize).Take(pageSize).Select(w => new FTSword7bitThesaurus(this, w, selectedKeys.Contains(w.Key)));
        }

最佳答案

问题在于,您的代码不仅需要非常大的连续内存块(通过 List<> 的数组),而且还必须为 ListView 中的每个条目分配额外的内存。 。我可以想象与 ListView 相关的开销速度非常快,并且导致了问题。

有一些具有不同复杂程度的解决方案:

  • 数据虚拟化 - 此解决方案最适合您的用户。本质上,该控件只会将其需要的行保留在内存中。当然,您的用户无法分辨,因此这是最好也是最复杂的解决方案。这个post有一个很好的例子。 (看起来像 Google 图片搜索)。
  • 控制分页 - 该解决方案看起来更像是一个网站选项。想想普通的谷歌,他们不会向你展示无限的结果,只是一个子集。然后,他们让您选择下一页以获得更多结果。使用 IEnumerable<> 可以很好地完成此操作。因为你可以使用Skip()Take()对于每页(假设每页有 25 个条目,那么您将执行 Skip(25 * pageNumber).Take(25) )。我发现这个解决方案更容易创建,但使用起来却更麻烦。

关于.net - 集合内存不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21121241/

相关文章:

android - java.lang.OutOfMemoryError 即使在 try-catch block 中?

c# - 使用 EPPlus 生成的 Excel 文件中的内容不可读

c# PayPal Access Token 不返回任何东西,尽管连接是 "OK"

java - 我应该如何迭代 HashSet、删除某些元素并更改其他元素?

通过套接字发送图像时的Java OutOfMemory

cuda - 在我的程序中分配统一内存。运行后,它抛出 CUDA 错误 :out of memory, 但仍有可用内存

c# - ASP.NET VNext 是云优化的是什么意思?

c# - 在 .NET Standard 库中使用动态

c# - NHibernate 集合映射哪一个更好?

java - 使用 spring 表达式语言 (SpEL) 更新集合中的属性