我可以对ReleaseComObject有所了解吗?我可以忽略它吗?

Che*_*vas 6 .net c# com vsto com-interop

我一直在VBA开发办公室解决方案已有一段时间了,并且对VBA中的办公室开发有相当完整的了解.我已经决定是时候用.Net学习一些真正的编程了,并且遇到了一些问题.

浏览了大量文章和论坛(此处和其他地方),在使用COM对象时,似乎有一些关于.Net内存管理的混合信息.

有人说我应该总是确定性地释放COM对象,而其他人说我几乎不应该这样做.

人们说我应该这样做:

第861页的"专业Excel开发"一书.

这个堆栈交换问题已经回答说"必须释放你对COM对象的每个引用.如果你没有,那么进程将留在内存中"

这篇博客建议使用它来解决他的问题.

人们说我不应该这样做:

这篇由Eric Carter撰写的MSDN博客指出"在VSTO场景中,您通常不必使用ReleaseCOMObject."

由Eric Carter共同撰写的"VSTO for Office 2007"本书似乎没有提及任何内存管理或ReleaseComObject.

这篇由Paul Harrington撰写的MSDN博客说不要这样做.

有混合建议的人:

Jake Ginnivan说我应该总是在没有离开方法范围的COM对象上做这件事.如果COM对象离开方法范围,则忘记它.为什么我不能一直忘记它呢?

Paul Harrington的博客似乎暗示MS的建议在过去的某个时候发生了变化.调用ReleaseCOMObject曾经是最佳实践,但现在不是了吗?我可以将更精细的内存管理细节留给MS,并假设一切都很好吗?

nos*_*tio 2

我尝试在有关 的互操作开发中遵守以下规则ReleaseComObject

如果我的托管对象实现某种类似于 的关闭协议IDisposable,我将调用ReleaseComObject我持有引用的任何子 COM 对象。我正在谈论的关闭协议的一些示例:

  • IObjectWithSite.SetSite(null)
  • IOleObject.SetClientSite(null)
  • IOleObject.Close()
  • IDTExtensibility2.OnDisconnection
  • IDTExtensibility2.OnBeginShutdown

  • IDisposable.Dispose本身

这有助于打破 .NET 和本机 COM 对象之间潜在的循环引用,因此托管垃圾收集器可以无障碍地完成其工作。

也许,有类似的东西可以在您的 VSTO 互操作场景中使用(AFAIR,IDTExtensibility2在那里相关)。

如果互操作场景涉及 IPC COM 调用(例如,当您将托管事件接收器对象传递到进程外 COM 服务器(如 Excel)时),则还有另一个选项可以跟踪对托管对象的外部引用:IExternalConnection接口IExternalConnection::AddConnection/与/ReleaseConnection非常相似,但当从另一个 COM 公寓(包括驻留在单独进程中的公寓)添加引用时,它们会被调用。IUnknown::AddRefRelease

IExternalConnection提供了一种为进程外场景实现几乎通用的关闭机制的方法。当外部引用计数达到零时,您应该调用ReleaseComObject您可能持有引用的任何外部 Excel 对象,从而有效地打破进程和 Excel 进程之间任何潜在的循环 COM 引用。也许,类似这样的事情已经由 VSTO 运行时实现了(我对 VSTO 没有太多经验)。

也就是说,如果没有明确的关闭机制,我不会调用ReleaseComObject. 另外,我从来不使用FinalReleaseComObject.