我用List 命中了OutOfMemoryException – 这是限制还是我遗漏了什么?

如果有机会重写,我会,但无论如何,代码如下:

List foobar; 

然后我们将一堆字符串添加到foobar。

在count = 16777216时,我们达到了内存不足限制。

我的理解是每个字符串的大小不同。 确实在查看数据(不是我的数据),大多数是2或3个字符。

c#中数据的最大限制是多少? 表示最大限制为:

可以存储在List的当前实现中的最大元素数量理论上是Int32.MaxValue – 仅超过20亿。

然而:

在当前的CLR的Microsoft实现中,最大对象大小限制为2GB。 (有可能其他实现,例如Mono,没有这个限制。)

在我的例子中,我有,1600万个结果*几个字节? 任务管理器显示正在使用的演出,但我有8演出的RAM。

16777216(2 ^ 24)似乎是一个相当具体的价值 – 可疑地像一个限制,但我找不到任何文件a)支持这个或b)找到解决方法?

任何帮助,将不胜感激。


一些代码:

 List returnList = new List(); SqlDataReader dr; // executes a read on a database, have removed that part as that bit works fine if (dr.HasRows) { while (dr.Read()) { returnList.Add(dr.GetString(0).Trim()); } } 

这是简化forms,我现在有一些尝试/捕获OOMexception,但这是给我悲伤的实际代码。

如果您尝试在64位环境中使用非常大的列表,则需要在应用程序配置中启用大型对象。

http://msdn.microsoft.com/en-us/library/hh285054.aspx

OOM可能是由于Lists / ArrayLists分配内存的方式,我相信每次达到它们的边界时,它们都会尝试将内存加倍。 该列表不能从2 ^ 24加倍。 理论上,您可以通过预先指定大小来最大化列表大小。 (即2GB)

我已经发布了我在这里所做的一切,值得一试。 再次步骤是:

  1. 在每次迭代中使用存储过程查询数据部分
  2. 转移他们
  3. 转到下一部分

     List returnList; int index = 0; SqlCommand cmd = new SqlCommand("ExampleStoredProc", conn); cmd.CommandType = CommandType.StoredProcedure; while (true) { cmd.Parameters.Add( new SqlParameter("@index", index)); SqlDataReader dr = cmd.ExecuteReader(); if (dr.HasRows) { returnList = new List(); returnList.Add(dr.GetString(0).Trim()); //transfer data here } else { break; } index++; } 

并且存储的proc应该是这样的:

 CREATE PROCEDURE ExampleStoredProc @index INT AS BEGIN SELECT * FROM veryBigTable WHERE Id >= (@index *1000) AND Id < ((@index + 1) * 1000) END GO 

无论你有多少记录,我肯定会工作,你拥有的数据越多,完成的时间就越长。

如果手动设置正确的列表大小时,它甚至会少于2 ^ 24,那么这可能是在正确的轨道上。 而不是达到1600万,然后尝试加倍列表的大小,它将使列表真的很大,开始和早先耗尽内存。

这就解释了为什么你得到一个圆数 – 它达到2 ^ 24然后试图增加大小,这导致它使用太多的内存。

听起来像是某种“自然”对象大小限制,而不是列表实现中的一个。