Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# OutofMemory异常对象数组大小_C#_.net_Data Structures - Fatal编程技术网

C# OutofMemory异常对象数组大小

C# OutofMemory异常对象数组大小,c#,.net,data-structures,C#,.net,Data Structures,我正在尝试将电子表格数据捕获到2D数组中。我正在使用VSTO int rc = 1048576; int cc = 1638; string[,] arr = new string[rc, cc]; 最后一行抛出内存不足异常。我想显示一条消息,告诉用户只能捕获“X”元素 检查了MSDN,并提到行数限制为16777216。datatable没有列计数限制。也找不到二维阵列的限制 我的问题不是为什么例外。我要寻找的是,如果您正在进行VSTO开发,并且必须在数据表中捕获一个工作表以执行内存中的联接

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

int rc = 1048576;
int cc = 1638;

string[,] arr = new string[rc, cc];
最后一行抛出内存不足异常。我想显示一条消息,告诉用户只能捕获“X”元素

检查了MSDN,并提到行数限制为16777216。datatable没有列计数限制。也找不到二维阵列的限制

我的问题不是为什么例外。我要寻找的是,如果您正在进行VSTO开发,并且必须在数据表中捕获一个工作表以执行内存中的联接等,则需要执行以下操作:

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

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

让我们来计算一下。您正在尝试分配一个包含1048576*1638=1717567488个元素的二维字符串数组。x64上的字符串引用大小为8字节=>总计1717567488*8=13740539904字节。大约是13GB的连续内存空间。CLR单次分配的最大大小为2GB,所以您将获得OutOfMemoryException,因为无法分配这样的单块

请注意,即使所有字符串的长度都为1-2个字符,除了引用之外,字符串值也需要30GB。除了一个
OutOfMemoryException
之外,您还希望得到什么呢?

Aleks, 您正在请求限制内存分配。 让我建议改变你的观点和看法 限制你的输入

  • 1.1仅使用用户选择的单元格
  • 1.2仅使用xl.工作表中实际使用的单元格
除了您的问题,我建议您注意
Range.Value
Range.Value2
:Range.Value之间的差异。Value包含用户输入,例如
=SUM(A1:B10)
,而Range.Value2包含该公式的结果,例如
10


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


1.2仅使用xl.工作表中实际使用的单元格
使用
工作表.Cells.SpecialCells
属性。
也许
工作表。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

我的向下投票感觉表明,当你试图分配一块内存,大小相当于机器的整个地址空间时,你不应该真的期望有什么不同。OP不应该对结果感到惊讶,但我不确定我是否同意所有的向下投票。这是一个公平的问题,一个简单的解释就足够了。但这个问题似乎表明研究工作不力。异常正好指出了错误所在,从数学的角度来看,很明显,如果要分配20亿的东西,最好把它弄得很小。缓冲区溢出,我建议创建一个新的问题,因为原来的版本本身是半有用的,而您的编辑完全改变了问题的内容(即使从您的角度来看是同一个问题)。并获得“在Excel interop中处理大范围选择”之类的新标题。谢谢。我已经把新问题放在下面,字符串是否通过引用存储?如果是,这将只分配大约6GB(仍然太大,但小于28GB)。我同意Wug:string是一种引用类型,创建字符串数组将使用
null
而不是
string.Empty
初始化数组中的每个项。空字符串是一个8字节的对象头(4字节SyncBlock和4字节类型描述符)+字符串长度的int32字段(由string.length返回)+字符缓冲区中字符数的int32字段+系统中字符串的第一个字符。字符=18字节。因此,即使字符串为空(这里就是这种情况)您仍然需要相同数量的引用。@DanielHilgarth:即使它将它们全部初始化为string.Empty,也可能会创建一个6GB的引用数组来引用同一对象。@DarinDimitrov:still:With
new string[rc,cc]
您不创建
rc*cc
字符串实例。数组中的每个项都将用
null
初始化。即使每个项都是
字符串。空的
也不会因为字符串插入而改变任何内容。我对此投了否决票,因为即使您将
范围.Value2
强制转换为
对象[,]
,默认情况下,数组为空。如果像我的情况一样,一个工作簿中有154列,则填充数组仍将导致System.OutOfMemoryException