Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.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#Excel OutOfMemory因插入到某个范围而导致异常_C#_Excel_Memory_Out Of Memory_Vsto - Fatal编程技术网

C#Excel OutOfMemory因插入到某个范围而导致异常

C#Excel OutOfMemory因插入到某个范围而导致异常,c#,excel,memory,out-of-memory,vsto,C#,Excel,Memory,Out Of Memory,Vsto,我一直在从事一个相当复杂的C#VSTO项目,该项目在Excel中完成了许多不同的工作。然而,我最近偶然发现了一个我不知道如何解决的问题。我担心把整个项目放在这里会使我的问题过于复杂,让每个人都感到困惑,所以这就是问题所在: //this is a simplified version of Range declaration which I am 100% confident in Range range = worksheet.Range[firstCell, lastCell] rang

我一直在从事一个相当复杂的C#VSTO项目,该项目在Excel中完成了许多不同的工作。然而,我最近偶然发现了一个我不知道如何解决的问题。我担心把整个项目放在这里会使我的问题过于复杂,让每个人都感到困惑,所以这就是问题所在:

//this is a simplified version of Range declaration which I am 100% confident in
Range range = worksheet.Range[firstCell, lastCell] 

range.Formula = array; 
//where array is a object[,] which basically contains only strings and also works perfeclty fine
最后一行应该插入[,]数组到Excel范围,以前用于较小的Excel书籍,但现在对于具有
System的较大书籍崩溃。OutOfMemoryException:内存不足,无法继续执行程序,我不知道为什么,因为它曾经在一个维度上处理500多个元素的数组,而现在它在处理400个元素以下的数组时崩溃。此外,在崩溃时,RAM的使用量约为1.2GB,我知道该项目能够以~3GBs的RAM使用量完美运行

我尝试过以下方法:逐行插入此数组,然后逐单元格插入,在每次插入行或单元格之前调用GC.Collect(),但它仍会因
系统.OutOfMemoryException
而崩溃

因此,如果您能帮助我解决这个问题或确定错误可能隐藏在何处,我将不胜感激,因为我无法理解为什么它拒绝在1.2GBs的RAM使用级别下,对长度较小(但可能包含稍大的内容)的阵列工作,这相当于它过去处理的1/3。谢谢大家!

编辑

我在评论中被告知,上面的代码可能过于稀疏,因此这里有一个更详细的版本(我希望它不会太混乱):

列表控件列表=新列表();
//这个列表中充满了一个相当长的方法,它调用了许多其他函数
//如果其他部分看起来不错,我想我得调查一下
int totalRows=1;
foreach(controlsList中的var控制)
{
if(control.Length==0)
继续;
var range=worksheet.GetRange(totalRows+1,1,totalRows+=control.Length,11);
//控件是一个对象[n][11],因此通常插入时不会出现索引问题
range.Formula=control.To2dArray();
}
//GetRange和To2dArray是扩展方法
公共静态范围GetRange(此工作表,int firstRow,int firstColumn,int lastRow,int lastColumn)
{
var firstCell=sheet.GetRange(第一行,第一列);
var lastCell=sheet.GetRange(lastRow,lastColumn);
返回(范围)表。范围[firstCell,lastCell];
}
公共静态范围GetRange(此工作表工作表,int行,int列)=>(范围)工作表。选中正(行,列)。单元格[行,列];
public static T CheckIsPositive(此T返回值,参数int[]vals)
{

若有(VAL.Any)(x=>x我不能100%确定我是否正确地计算了它,但问题似乎在于Interop.Excel/Excel的限制和我试图插入的公式长度:每当长度接近8k个字符,即公式内容的Excel限制时,
系统.OutOfMemoryException
就会弹出。当我选择为了省去冗长的公式,程序开始运行良好。

firstCell
lastCell
的值是多少?
数组的维度大小是多少?
锯齿状数组中有什么类型的对象?代码似乎太稀疏,无法排除值太大而导致问题,因为通常最快的方法是使用探查器,在堆运行时查看堆。如果你有vs enterprise,它有一个内置的探查器,如果没有第三方的探查器。请注意,你也不能比较调试和发布行为。正如@MartinCostello所说,如果没有更多的de,很难提供更多详细说明范围到底有多大以及数组中有什么。您的目标是将数组的内容插入指定范围内的每个单元格吗?@MartinCostello我在编辑中提供了与问题相关的代码,谢谢!希望问题不在于列表填充方法(我没有发布)因为它不会在那里崩溃,而且由于它的复杂性,很难进行调查。@MikeJ堆中有什么特别的东西需要注意吗?我不太熟悉内存处理,所以如果您指出可能导致内存泄漏的原因(我在编辑中添加了一些代码),我将不胜感激,谢谢!
List<object[][]> controlsList = new List<object[][]>();
// this list is filled with a quite long method calling a lot of other functions
// if other parts look fine, I guess I'll have to investigate it

int totalRows = 1;

foreach (var control in controlsList)
{
    if (control.Length == 0)
        continue;

    var range = worksheet.GetRange(totalRows + 1, 1, totalRows += control.Length, 11);
    //control is an object[n][11] so normally there are no index issues with inserting
    range.Formula = control.To2dArray();
}

//GetRange and To2dArray are extension methods
public static Range GetRange(this Worksheet sheet, int firstRow, int firstColumn, int lastRow, int lastColumn)
{
    var firstCell = sheet.GetRange(firstRow, firstColumn);
    var lastCell = sheet.GetRange(lastRow, lastColumn);

    return (Range)sheet.Range[firstCell, lastCell];
}

public static Range GetRange(this Worksheet sheet, int row, int col) => (Range)sheet.CheckIsPositive(row, col).Cells[row, col];

public static T CheckIsPositive<T>(this T returnedValue, params int[] vals)
{
    if (vals.Any(x => x <= 0))
        throw new ArgumentException("Values must be positive");

    return returnedValue;
}

public static T[,] To2dArray<T>(this T[][] source)
{
    if (source == null)
        throw new ArgumentNullException();

    int l1 = source.Length;
    int l2 = source[0].Length(1);

    T[,] result = new T[l1, l2];

    for (int i = 0; i < l1; ++i)
        for (int j = 0; j < l2; ++j)
            result[i, j] = source[i][j];

    return result;
}