简体   繁体   English

Excel 2010 com对象引用未发布

[英]Excel 2010 com object references not released

The following code sample worked just fine in Excel 2007, but when I installed Excel 2010 (32bit) it would leave the excel.exe process open unless I added the GC.Collect(). 以下代码示例在Excel 2007中运行良好,但是当我安装Excel 2010(32位)时,除非我添加了GC.Collect(),否则将保持excel.exe进程处于打开状态。 My simple question is am I doing something wrong? 我的简单问题是我做错了什么? It looks like to me like I am releasing everything I use. 在我看来,我正在释放我使用的所有东西。

    public override void Update()
    {

        StatusBox.AddStatus("Opening File " + ImportPath);

        Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
        Microsoft.Office.Interop.Excel.Workbook wb = app.Workbooks.Open(ImportPath, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
        Microsoft.Office.Interop.Excel.Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Sheets[1];

        Range rng = ws.Cells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing);

        int LastRow = rng.Row;

        StatusBox.AddStatus(LastRow.ToString() + " Rows Found in File");


        StatusBox.AddStatus("Closing File " + ImportPath);

        System.Runtime.InteropServices.Marshal.ReleaseComObject(rng);
        rng = null;

        System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
        ws = null;

        wb.Close(true, ImportPath, null);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
        wb = null;

        GC.Collect();

        app.Quit();
        System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
        app = null;
    }

You need to call both GC.Collect / GC.WaitForPendingFinalizers and Marshall.FinalReleaseComObject. 您需要同时调用GC.Collect / GC.WaitForPendingFinalizers Marshall.FinalReleaseComObject。

See my answer here for details: 有关详细信息,请参阅我的答案

How do I properly clean up Excel interop objects? 如何正确清理Excel互操作对象?

Note that the advice (and apparently the more popular answer) to "never use two dots" in any given command is valid, but virtually impossible to enforce in practice. 请注意,在任何给定命令中“永不使用两个点”的建议(显然是更受欢迎的答案)是有效的,但实际上几乎不可能实施。 If you make any mistake anywhere in your code, the Excel application will hang and there is no profiling tool on the planet that can help you -- you'd have to review all your code by eye. 如果您在代码中的任何位置出现任何错误,Excel应用程序将挂起,并且地球上没有可以帮助您的分析工具 - 您必须通过眼睛检查所有代码。 For a large code base, this is essentially impossible. 对于大型代码库,这基本上是不可能的。

In your code, you do not have a call to GC.WaitForPendingFinalizers after your call to GC.Collect. 在您的代码中,在调用GC.Collect之后,您没有调用GC.WaitForPendingFinalizers。 This is necessary to ensure that your garbage collection calls are synchronous. 这是确保垃圾回收调用是同步的必要条件。 (GC.Collect operates on a different thread, if you don't wait for it, the collection could occur out of order with respect to your subseqent object releases and you want to release minor COM objects, like Ranges, first, and the major COM objects like Workbooks and the Application, last.) After calling GC.Collect and GC.WaitForPendingFinalizers, you would then want to call Marshall.FinalReleaseComObject on your named references. (GC.Collect在不同的线程上运行,如果你不等它,那么集合可能就你的subseqent对象版本而无序发生,并且你想要释放次要的COM对象,比如Ranges,首先和主要的最后一个COM对象,如Workbooks和Application。)在调用GC.Collect和GC.WaitForPendingFinalizers后,您需要在命名引用上调用Marshall.FinalReleaseComObject。

So, in short, the strategy is to call GC.Collect and GC.WaitForPendingFinalizers to release the COM objects to which you do not hold a reference and call Marshall.FinalReleaseComObject to release the COM objects to which you do hold a named reference. 因此,简而言之,策略是调用GC.Collect和GC.WaitForPendingFinalizers来释放您没有引用的COM对象,并调用Marshall.FinalReleaseComObject来释放您持有命名引用的COM对象。

-- Mike - 迈克

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM