如何在C#中正确清理Interop对象

5
这是一个关于下一步问题的提问,与如何正确清理C#中的Excel互操作对象相关。
要点是,在Excel命名空间中使用链接调用(例如ExcelObject.Foo.Bar())会阻止COM对象的垃圾收集。相反,应该显式创建对每个使用的COM对象的引用,并使用Marshal.ReleaseComObject()显式释放它们。
在链接调用后不释放COM对象的行为是否仅适用于Excel COM对象?是否过度运用此类模式,无论何时使用COM对象都要这样做?
2个回答

6
处理Office应用程序的发布比许多其他COM库更为重要,原因有两点:
  1. Office应用程序作为进程外服务器运行,而不是进程内库。如果您未能正确清理,将会留下一个运行中的进程。
  2. 如果存在对其COM对象的未完成引用,Office应用程序(特别是Excel,如果我没记错)即使调用Application.Quit也无法正确终止。
对于常规的进程内COM库,未能正确清理的后果并不那么严重。当进程退出时,所有进程内库都会随之消失。如果您忘记在不再需要对象时调用ReleaseComObject,则在对象得到最终处理时它仍将被处理。
话虽如此,这并不是写松散代码的借口。

非常好的观点关于为什么必须清理办公室interop对象。 - Anonymous Type

2

COM对象本质上是不受管理的代码,一旦您开始从托管应用程序调用不受管理的代码,就需要负责清理该不受管理的代码。

简而言之,上述帖子中链接的模式对于所有COM对象都是必要的。


...对于某些“必要”的定义。在进程关闭时(或者如果先发生应用程序域卸载),我相信所有尚未被销毁的RCW(运行时可调用包装器)都将被释放。不幸的是,它们正确地被销毁并执行所有终结器没有强有力的保证。除此之外,如果销毁COM对象需要超过2秒钟的时间,CLR将终止在该线程上执行的所有终结器队列。 - reuben
2
@Reuben,请仔细阅读问题,答案对于所提出的问题是100%正确的,然而有关COM的伟大内在细节与此问题无关。 - Akash Kava

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接