8

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

  1. 如果我们访问 Document 对象,是否需要对其调用 release?或者我们可以假设 Word 已经访问过它并会清理它吗?
  2. 如果我们访问给我们一个字符串的 Document.Name。由于字符串不是 COM 对象,我们不需要清理它——对吗?
  3. 但是,如果我们访问返回包装 COM 对象的类的任何成员(这是由成员方法/函数返回的任何类),我们确实需要调用 release - 对吗?

如果我们错过了发布,会发生什么?我们持有的任何 COM 对象的时间不确定,我们将其包装在一个实现了 IDisposable 的类中。完成后我们调用 Dispose()。但是一些处理这个的代码很复杂,我猜我们偶尔会遇到我们不调用 Dispose 的情况。

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

谢谢 - 戴夫

4

1 回答 1

3

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

不包括您未明确引用的值类型(字符串等)和子 COM 对象。

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

要解决您的具体问题:

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

  2. 如果我们访问给我们一个字符串的 Document.Name。由于字符串不是 COM 对象,我们不需要清理它——对吗?-- 你不需要清理值类型。

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

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

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

于 2012-05-07T15:38:44.823 回答