我什么时候需要调用ReleaseComObject?

时间:2012-05-06 18:22:07

标签: .net com office-interop

在Microsoft Office AddIn中,我们在事件中传递COM对象。举一个特定的情况,当Word打开一个文档时,我们被调用并传递一个Document对象。那么我们什么时候需要调用Marshal.ReleaseComObject()?

  1. 如果我们访问Document对象,我们需要调用它吗?或者我们可以假设Word已经访问过它并将其清理干净吗?
  2. 如果我们访问为我们提供字符串的Document.Name。由于字符串不是COM对象,我们不需要清理它 - 正确吗?
  3. 但是如果我们访问任何返回包含COM对象的类的成员(这是由成员方法/函数返回的任何类),我们确实需要调用release - 对吗?
  4. 如果我们错过了发布会怎么样?我们在不确定的时间内保留的任何COM对象都包含在我们的IDIposable实现的类中。我们完成后调用Dispose()。但是处理这个问题的一些代码很复杂,我猜我们偶尔会遇到一个不调用Dispose的情况。

    我们最好有一个终结器,然后为这些对象的每个实例增加开销(很多!)?或者我们最好使用少量从未发布过的Word COM对象?

    谢谢 - 戴夫

1 个答案:

答案 0 :(得分:3)

简而言之,必须释放您对COM对象的每个引用。如果不这样做,该过程将留在内存中。

排除了值类型(字符串等)和未明确引用的子COM对象。

一个例外可能是作为事件参数传递给您的COM对象。我认为你不需要发布它们但我不确定。然而,快速测试应该证实这一点。 (尝试使用和不释放COM对象的加载项。看看加载项是否开始表现得很有趣,或者在应用程序关闭后是否有任何相关进程继续运行。)

解决您的具体问题:

  1. 如果我们访问Document对象,我们需要调用它吗?或者我们可以假设Word已经访问过它并将其清理吗? - 你必须释放它。

  2. 如果我们访问为我们提供字符串的Document.Name。由于字符串不是COM对象,我们不需要清理它 - 正确吗? - 您不需要清理值类型。

  3. 但是如果我们访问任何返回包装COM对象(由成员方法/函数返回的任何类)的类的成员,我们确实需要调用release - 对吗? - 如果您没有明确引用它,则无需释放它。 (有一些例外。例如在这个question of mine中我发现一个特定的COM方法实例化一个COM对象并且从不释放它。由于我无法控制方法实现,我唯一的选择是避免使用该方法。)

  4. 如果我们错过了发布会怎么样? - 进程(winword.exe,excel.exe等)将保留在内存中。随着时间的推移,所有这些未终止的进程将耗尽机器上的所有可用内存。

  5. 我们最好有一个终结器,然后为这些对象的每个单个实例增加开销(很多!)?或者我们最好使用少量从未发布的Word COM对象? - 你最好使用终结器。始终释放您的COM对象!我发现here概述的步骤是最有效的。 (这些步骤使用FinalReleaseComObject,它比ReleaseComObject更受欢迎。)我还建议不要杀死Office进程作为不释放COM的替代方法。随着时间的推移,这将导致Office互操作问题(我从未完全理解)。