【发布时间】:2012-05-08 00:48:56
【问题描述】:
在 Microsoft Office 插件中,我们通过事件传递 COM 对象。举一个特定的例子,当 Word 打开一个文档时,我们被调用并传递了一个 Document 对象。那么我们什么时候需要调用 Marshal.ReleaseComObject() 呢?
- 如果我们访问 Document 对象,是否需要对其调用 release?或者我们可以假设 Word 已经访问过它并会清理它吗?
- 如果我们访问给我们一个字符串的 Document.Name。由于字符串不是 COM 对象,我们不需要清理它 - 对吗?
- 但是,如果我们访问返回包装 COM 对象的类的任何成员(即由成员方法/函数返回的任何类),我们确实需要调用 release - 对吗?
如果我们错过一个版本会发生什么?我们持有的任何 COM 对象的时间不确定,我们将其包装在一个实现了 IDisposable 的类中。完成后我们调用 Dispose()。但是处理这个问题的一些代码很复杂,我猜我们偶尔会遇到不调用 Dispose 的情况。
我们最好有一个终结器,然后为这些对象的每个实例增加开销(很多!)?还是我们最好使用少量从未释放的 Word COM 对象?
谢谢 - 戴夫
【问题讨论】:
-
关于这个的问题已经有数百个,通过方法名很容易找到。一遍又一遍的相同主题,RCW 是一个托管对象,因此遵守垃圾回收生命周期规则。你用 GC.Collect 强制收集
-
我在 S/O 上通读了 12 个项目。以上是我阅读完所有这些后留下的问题。 MS Office COM 对象有点复杂,因为您不确定 Office 到底在做什么。
-
COM只有一种,Office没有使用它的特殊版本。对象模型越复杂,用 ReleaseComObject 打猴子的可能性就越小。这就是为什么你把它留给垃圾收集器,它永远不会错过任何一只猴子。
-
黑魔法在软件工程中没有立足之地。使用 C# 版本 4 中允许的语法扩展,还有很多方法可以错过猴子。 Range.Cell[x, y].Value 语法非常适合隐藏 3 只完全不可打孔的猴子,因为你没有在任何地方分配接口引用。这就是为什么你把它留给垃圾收集器。
-
是的,这是一种非常流行的错觉。否则,这并不能使它成为正确的错觉。只有沙华鱼人做对了。这种情况一遍又一遍地出现,因为每个人都在做错事,这是很难避免的。出于完全相同的原因,编写一个不泄漏内存的 C 程序很难做到。显然我无法说服你,这并不重要。通过发布一个显示问题的 sn-p 来使这个问题成为一个真正的问题。
标签: .net com office-interop