我用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)
我已经发布了我在这里所做的一切,值得一试。 再次步骤是:
- 在每次迭代中使用存储过程查询数据部分
- 转移他们
-
转到下一部分
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然后试图增加大小,这导致它使用太多的内存。
听起来像是某种“自然”对象大小限制,而不是列表实现中的一个。