我有一个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文件并从内存中退出?
谢谢。
答案 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");
}