【问题标题】:Releasing Com Objects释放 Com 对象
【发布时间】:2015-09-25 06:15:52
【问题描述】:

我遇到了 EXCEL 应用程序在任务管理器中保持打开状态的问题,即使在我通过代码清理(或认为我正在清理)之后也是如此。谁能指出我在下面的代码的 sn-p 中缺少什么:

private void btnBrowseSquid_Click(object sender, EventArgs e)

        //starting up and defining the Excel references
        Excel.Workbook squidBook = null;
        Excel.Application excelApp = null;
        Excel.Worksheet squidSheet = null;
        string squidFileName = txtSquid.Text;

        //Reading the information from the "Filenames" tab of the SQUID file into the Windows Form
        excelApp = new Excel.Application();
        excelApp.Visible = true;
        squidBook = excelApp.Workbooks.Open(squidFileName);
        squidSheet = squidBook.Sheets["Filenames"];

        //do stuff here with the excel file

        //close the open Excel App
        squidBook.Close();
        excelApp.Quit();
        Marshal.FinalReleaseComObject(squidSheet);
        Marshal.FinalReleaseComObject(squidBook);

    }

【问题讨论】:

  • 你可能有一个旧的进程,因为你的代码没有到达最后的失败尝试......
  • 手动内存管理永远不起作用,有一个 WorkSheets 接口引用在您的代码中完全不可见。并且不可避免地你忘记了释放它。只需停止编写这样的代码,没有意义,垃圾收集器永远不会出错。 Read this.

标签: c# excel com interop


【解决方案1】:

还请执行以下操作:

Worksheets sheets = excelApp.Worksheets; 
Marshal.ReleaseComObject(squidSheet);
Marshal.ReleaseComObject(squidBook );
Marshal.ReleaseComObject(sheets);
squidSheet = null;
squidBook = null;
sheets = null;
GC.Collect();
GC.WaitForPendingFinalizers();

您必须释放工作表,因为您通过执行以下语句持有对它的引用:

squidSheet = squidBook.Sheets["Filenames"];

【讨论】:

  • 我添加了这些,但遗憾的是我仍然在同一条船上。一个 EXCEL 实例保持打开状态
  • 确保您的其他引用也设置为空。
  • 我没有投反对票,但我建议您查看 Hans 对原始问题的评论以进行澄清。
  • 汉斯的评论对 OP 没有帮助。老实说,我不明白为什么人们在试图提供帮助时投反对票。 OP,也添加了工作表,因为您也持有对它的引用。请尝试,如果仍然无效,我将删除此答案,因为我不知道您还持有什么其他参考资料。
  • Hans 的回答解释了为什么手动内存管理是一个常见的误解,以及为什么释放这样的对象是不必要的。它解释了如何正确释放垃圾以及 OP 观察到的行为可能是由于调试怪癖造成的。如果我误解了,那么我肯定希望得到纠正,我总是很高兴学习一种掌握 Office Interop 野兽的新方法:-)
【解决方案2】:

你可能有一个旧的进程,因为你的代码没有到达最后的尝试失败......

尝试在运行代码之前完成它。 (确保您没有打开其他 Excel 应用程序)。

当您确定您的代码永远不会失败时,运行它并看到应用程序从进程列表中消失。

【讨论】:

  • 在启动程序之前,我没有打开任何 EXCEL 实例(在任务管理器中验证)。即使按照 Philip 添加了 GC 代码,它仍然是开放的,并且非常痛苦……嗯
  • 您确定在do stuff 期间没有打开任何其他新应用程序吗?这应该真的很好。
【解决方案3】:

使用 Office Interop 可能会很棘手,因为清理代码中有很多错误。您是否尝试过将代码减少到最低限度并向外扩展直到问题重现(例如,创建应用程序,退出应用程序;Excel.exe 是否挂起?创建应用程序,加载工作簿,关闭工作簿,退出应用程序; Excel.exe 会挂掉吗?...)?

说了这么多,我上次遇到这个问题(使用 Outlook)的根本原因是因为默认互操作层没有正确释放事件挂钩 - 所以我必须明确地这样做。为一些挫折做好准备,但通过一些实验,您应该能够将其运行下来。

【讨论】:

    【解决方案4】:

    我能够遵循@Philip 的建议并将 ExcelApp 也清空,然后像下面一样发布了 COM 对象,并且它起作用了。感谢您的帮助。

     //close the open Excel App
            squidBook.Close();
            excelApp.Quit();
            Marshal.FinalReleaseComObject(squidSheet);
            Marshal.FinalReleaseComObject(squidBook);
            Marshal.FinalReleaseComObject(excelApp);
            excelApp = null;
            squidSheet = null;
            squidBook = null;
            GC.Collect();
            GC.WaitForPendingFinalizers();
    

    【讨论】:

    • 很高兴我能帮上忙。您可以将此表示为 aswer。如果您还没有将我的回答标记为有帮助,我会很高兴;-)
    猜你喜欢
    • 2012-09-17
    • 2015-07-09
    • 1970-01-01
    • 1970-01-01
    • 2012-03-05
    • 2014-02-14
    • 1970-01-01
    • 2013-03-21
    相关资源
    最近更新 更多