OutofMemory异常对象数组大小

时间:2012-10-10 15:59:27

标签: c# .net data-structures

我正在尝试将电子表格数据捕获到2D数组中。我正在使用VSTO。

int rc = 1048576;
int cc = 1638;

string[,] arr = new string[rc, cc];

最后一行抛出Out of Memory异常。我想显示消息告诉用户只能捕获'X'元素。

已检查MSDN,并且提到的行数限制为16,777,216。无数据表的列数限制。无法找到2D阵列的限制。

我的问题不在于为什么例外。我正在寻找的是如果您正在进行VSTO开发,并且必须捕获DataTable中的工作表以执行内存中连接等,您将需要这样做:

string[,] arr = new string[rc, cc]; 
Microsoft.Office.Interop.Excel.Range selection 
arr = selection.Value as string[,]; 

然后将该数组中的数据复制到datatable。现在,用户应该选择的元素数量的理想限制是什么。因此,当选择超出此条件时,我可以设置rowcount / columncount lmits并显示消息。

2 个答案:

答案 0 :(得分:16)

我们来算一算。您正在尝试分配具有1048576 * 1638 = 1717567488元素的2D字符串数组。 x64上字符串引用的大小是8个字节=>共1717567488 * 8 = 13740539904字节。这是关于 13 GB 的连续内存空间。 CLR的单个分配的最大大小为2GB,因此您将获得OutOfMemoryException,因为无法分配单个块。

请注意,即使所有字符串都长1-2个字符,这样的字符串数量除了引用之外还需要30GB的字符串值。除了OutOfMemoryException你还期望得到什么呢?

答案 1 :(得分:0)

阿莱克斯, 你要求限制内存分配。 让我建议改变你的观点和 限制您的输入

  • 1.1仅使用用户选择的单元格
  • 1.2仅使用xl.worksheet中确实使用过的单元格

除了您的问题之外,我建议您注意Range.ValueRange.Value2的区别:Range.Value包含用户输入,例如:像=SUM(A1:B10)这样的公式,而Range.Value2包含该公式的结果,例如10

1.1仅使用用户选择的单元格
如上所述here使用Range userSelectedRange = Application.Selection;

1.2仅使用xl.worksheet中确实使用过的单元格 使用Worksheet.Cells.SpecialCells属性 也许Worksheet.UsedRange更好。

代码示例:

int lastUsedRowIndex = xlWorksheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell).Row;
int lastUsedColIndex = xlWorksheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell).Column;
string rangeString = string.Format("A0:{0}{1}", SomeIndexToExcelColConverterFunc(lastUsedColIndex), lastUsedRowIndex));
Xl.Range range = xlWorksheet.Range[rangeString];
object[,] objectMatrix = range.Value2 as object[,];
Marshal.ReleaseComObject(range);    
// convert to string here if needed