如何在C#中运行程序后释放内存?

时间:2016-03-05 06:19:36

标签: c# excel memory

我有一个C#程序,我在其中读取包含大约40000个数字的excel文件中的数据。这是我的代码的一部分:

        Microsoft.Office.Interop.Excel.Application _excelApp = new          Microsoft.Office.Interop.Excel.Application();
        _excelApp.Visible = true;
        string fileName = "D:\\data.xlsx";
        Workbook workbook = _excelApp.Workbooks.Open(fileName, Type.Missing);
        Worksheet worksheet = (Worksheet)workbook.Worksheets[1];
        Range excelRange = worksheet.UsedRange;
        Object[,] valueArray =    (object[,])excelRange.get_Value(XlRangeValueDataType.xlRangeValueDefault);
        int num = worksheet.UsedRange.Rows.Count;
        workbook.Close(false, Type.Missing);

        _excelApp.Quit();
        for (int row = 1; row <= num; ++row)
        {
            data1.Add(Convert.ToDouble(valueArray[row, 1]));
            data2.Add(Convert.ToDouble(valueArray[row, 2]));
        }

每次运行程序时,excel文件都会显示片刻并关闭。但是在windows的后台进程中有一些打开的excel文件,并消耗ram并降低windows的速度。如何在我的代码中完全关闭excel文件并从内存中退出?

谢谢。

2 个答案:

答案 0 :(得分:2)

您需要释放您使用的COM对象,以便它们可以正常关闭。

试试这段代码:

var _excelApp = new Microsoft.Office.Interop.Excel.Application();
_excelApp.Visible = true;
var fileName = "D:\\data.xlsx";
var workbooks = _excelApp.Workbooks;
var workbook = workbooks.Open(fileName, Type.Missing);
var worksheet = (Worksheet)workbook.Worksheets[1];
var excelRange = worksheet.UsedRange;
Object[,] valueArray = (object[,])excelRange.get_Value(XlRangeValueDataType.xlRangeValueDefault);
int num = worksheet.UsedRange.Rows.Count;

Marshal.FinalReleaseComObject(excelRange);
Marshal.FinalReleaseComObject(worksheet);

workbook.Close(false, Type.Missing);

Marshal.FinalReleaseComObject(workbook);
Marshal.FinalReleaseComObject(workbooks);

_excelApp.Quit();

Marshal.FinalReleaseComObject(_excelApp);

for (int row = 1; row <= num; ++row)
{
    data1.Add(Convert.ToDouble(valueArray[row, 1]));
    data2.Add(Convert.ToDouble(valueArray[row, 2]));
}

我还没有测试过这段代码,但它应该很接近。

请注意,您绝对必须执行此类代码:

var workbooks = _excelApp.Workbooks;
var workbook = workbooks.Open(fileName, Type.Missing);

......你不能这样做:

var workbook = _excelApp.Workbooks.Open(fileName, Type.Missing);

...因为这会使_excelApp.Workbooks中间对象无法释放。

答案 1 :(得分:-1)

您希望强制调用垃圾收集器,这通常通过调用 GC.Collect()来实现。

当您调用GC.Collect时,GC将在单独的线程上运行每个对象的终结器。因此,要记住的另一种方法是GC.WaitForPendingFinalizers。此同步方法在GC.Collect完成其工作之前不会返回。

示例:

public void MethodUsingTonsOfMemory(){
  // do memory intensive stuff

  GC.Collect();
  GC.WaitForPendingFinalizers(); // wait for memory to be released

  Debug.WriteLine("Memory should be clear now");
}