【发布时间】:2011-08-02 01:53:50
【问题描述】:
在将 COM Interop 与 Office(通常是 Excel)一起使用时,我始终小心确保在每次引用时都调用 Marshal.ReleaseComObject,以避免 Excel 不退出 as described in this KB article 的问题。
当我从 OOB Silverlight 应用程序(使用 AutomationFactory.CreateObject)使用 Interop 时,如何确保 Excel 退出?
Silverlight 没有 Marshal.ReleaseComObject 方法,甚至调用 GC.Collect 和 GC.WaitForPendingFinalizers 也无济于事。
在没有释放 COM 引用的机制的情况下,微软肯定没有将此功能添加到 Silverlight 吗?在我看来,这似乎是自动化进程外 COM 服务器(如 Excel)的最佳选择。
一个令人惊讶的遗漏,更何况 Pete Brown 在他的书“Silverlight 4 in Action”的第 5.5 节中谈到AutomationFactory.CreateObject,即:
此功能的主要目的是允许其他应用程序自动化,包括 Microsoft Office。
更新以回应 Hans 的 cmets。
我不相信 Office 应用程序的典型自动化中存在“无声刺客”问题。一个常见的用法可能类似于以下内容,我在 WinForms 应用程序中反复使用它,但从未遇到 Hans 链接的文章中描述的“中毒 RCW”:
- 创建一个 Excel.Application 实例
- 打开或创建工作簿
- 将数据写入工作簿
- 如果一切顺利,则显示 Excel,关闭工作簿并调用 Application.Quit,否则。
- 调用 Marshal.ReleaseComObject 释放所有 Excel 对象引用。
未能按照 Hans 的建议调用 Marshal.ReleaseComObject 将导致 Excel.exe 的多个副本运行,如上面提到的知识库文章中所述 - 非常不受欢迎。
更新 2
我用来复现的示例是来自 Pete Brown 的书 Silverlight 4 in action 的源代码示例,此页面上有下载链接。示例解决方案 AutomatingExcel 位于 Ch05.zip / 5.03 中。复制:
- 确保没有 Excel 实例正在运行
- 运行 AutomatingExcel 示例
- Excel 工作簿已打开
- 关闭 Excel
- 使用任务管理器观察 Excel 仍在运行。
将所有动态变量设置为 null 并调用 GC.Collect() 似乎可以正常工作,正如 AnthonyWJones 的回答中所指出的那样。
更新 2
Otaku 的答案是我一直在寻找的——通过将引用包装在 using 语句中,COM 引用被释放而无需调用 GC.Collect。一些实验表明,与上面引用的知识库文章中描述的标准Marshal.ReleaseComObject 解决方案不同,它更能容忍未能处理每个引用。
如果对必须处理的内容进行权威处理以确保释放所有 Excel 引用,将会很有趣。
【问题讨论】:
-
@Hans:Silverlight 在
Marshal类中没有这些方法。 -
@Anthony - 它解释了为什么这些方法都不是一个好主意。 “沉默的刺客”链接非常相关。
-
@Hans - “它解释了为什么这些方法都不是一个好主意” - 你能提出一个替代方案吗?请参阅问题更新。这也不是您链接的问题的副本。
-
找到真正的问题,为什么终结器线程不再运行了?通常的原因是“头灯中的鹿”的原因,您在完成互操作代码的调试后让您的程序停止做任何有趣的事情。
标签: silverlight com interop