Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/341.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/24.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自动化导致Excel内存泄漏_C#_Excel_Com_Automation_Interop - Fatal编程技术网

C#Excel自动化导致Excel内存泄漏

C#Excel自动化导致Excel内存泄漏,c#,excel,com,automation,interop,C#,Excel,Com,Automation,Interop,我正在尝试使用C#和COM互操作库来打开一组非常繁重的excel工作簿。我必须使用C#,因为我还需要启动宏,移动一些单元格,并启动公司使用的自定义excel外接程序 然后,我的程序退出,让工作簿保持打开状态,每个工作簿位于单独的excel实例中。我不希望在程序退出时关闭工作簿 问题是,当我的C#程序退出时,随着时间的推移,excel工作簿逐渐消耗更多内存,直到它们从原来的500 mb消耗了3.5 Gig内存 我过去常常用手打开作业本,而这些工作表从来没有消耗过那么多的内存。一旦我开始用C#打开它

我正在尝试使用C#和COM互操作库来打开一组非常繁重的excel工作簿。我必须使用C#,因为我还需要启动宏,移动一些单元格,并启动公司使用的自定义excel外接程序

然后,我的程序退出,让工作簿保持打开状态,每个工作簿位于单独的excel实例中。我不希望在程序退出时关闭工作簿

问题是,当我的C#程序退出时,随着时间的推移,excel工作簿逐渐消耗更多内存,直到它们从原来的500 mb消耗了3.5 Gig内存

我过去常常用手打开作业本,而这些工作表从来没有消耗过那么多的内存。一旦我开始用C#打开它们,它们就因为内存使用过度而开始崩溃。我的理论是,当我与COM Excel对象交互时,会产生内存泄漏

以下是我的原始代码:

using Excel = Microsoft.Office.Interop.Excel;
...
excelApp = new Excel.Application();
excelApp.Visible = true;
excelApp.Workbooks.Open(filename, misValue, misValue, misValue, misValue, misValue,
               true, misValue, misValue, misValue, misValue, misValue, misValue, misValue, misValue);
excelApp.Calculation = Excel.XlCalculation.xlCalculationAutomatic;
我读过关于如何使用封送来释放使用的内容,所以我现在尝试下面的代码,但是除了打开所有的工作表并查看它们是否消耗了太多数据之外,没有简单的方法来测试它

            excelApp = new Excel.Application();
            excelApp.Visible = true;
            Excel.Workbooks currWorkbooks = excelApp.Workbooks;
            Excel.Workbook currWorkbook = currWorkbooks.Open(filename, misValue, misValue, misValue, misValue, misValue,
               true, misValue, misValue, misValue, misValue, misValue, misValue, misValue, misValue);
            //excelApp.Calculation = Excel.XlCalculation.xlCalculationAutomatic;

            int x = Marshal.ReleaseComObject(currWorkbook);
            currWorkbook = null;

            int y = Marshal.ReleaseComObject(currWorkbooks);
            currWorkbooks = null;

在使用MS Office COM互操作库时,我遇到了一些避免内存泄漏的方法:

首先,“不要使用两点”是记住它的最佳方式,但基本上,始终为新变量指定一个新的COM对象引用,不要连锁调用成员,即使Intellisense鼓励这样做。链式调用在后台做了一些事情,阻止了.NET framework的正确发布。。以下是我用于启动Excel报告的一些代码:

//use vars for every COM object so references don't get leftover
//main Excel app
var excelApp = new Application();
var workbooks = excelApp.Workbooks;

//workbook template
var wbReport = workbooks.Add(@"C:\MyTemplate.xltx");

//Sheets objects for workbook
var wSheetsReport = wbReport.Sheets;
var wsReport = (Worksheet)wSheetsReport.get_Item("Sheet1");
其次,对按与创建相反的顺序创建的每个变量调用
Marshal.ReleaseComObject()
,并在执行此操作之前调用两个垃圾收集方法:

//garbage collector
GC.Collect();
GC.WaitForPendingFinalizers();

//cleanup
Marshal.ReleaseComObject(wsReport);
Marshal.ReleaseComObject(wSheetsReport);
Marshal.ReleaseComObject(wbReport);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelApp);

每次使用Excel时都使用此方案解决了我的内存问题,尽管这是一件乏味且令人遗憾的事情,我们无法像以前那样使用链接成员。

您已经将currWorkbook设置为null。。那你为什么要做两次呢。另外,Mashal.ReleaseComObject(currWorkBook)是您所需要的全部内容。为什么要尝试分配一个Int来检查对象是否已被释放。。你有什么错误吗我没有任何错误。问题是excel工作簿是这样开始的,慢慢地消耗越来越多的内存。您可能需要签出EPPlus()。我不确定它支持哪种类型的宏(它确实提到VBA是一种功能),但总体而言,我发现EPPlus比Excel Interop更高效,更不容易出错。有关更多详细信息,请参阅此伟大的Q/a:。请注意,后来的一些答案可能比公认的答案要好。啊,这可能是我养成习惯的原因。。我不记得我在哪里读过它,它是很久以前,所以我只是回答。。。该链接可能是最好的通读方式。:)+我在好几个地方读到过,用“两点”不好,但我不知道为什么。现在我知道了!这不管用。我的C#程序退出后,Excel中的内存使用率仍在增加。每次在打开新的excelApp之前,我都会调用GC.Collect()和GC.WaitForPendingFinalizers两次,然后是工作簿,最后是excelApp。我也从来没有对任何COM对象使用过两个句点。我想我没意识到你想在以后打开工作簿。。。您是否研究过从命令行打开并从
Workbook\u Open
方法运行宏之类的方法?这只会是一个问题,如果你开始使用C#来处理你的细胞。。。