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,并假设一切都很好吗?
我尝试在有关 的互操作开发中遵守以下规则ReleaseComObject。
如果我的托管对象实现某种类似于 的关闭协议IDisposable,我将调用ReleaseComObject我持有引用的任何子 COM 对象。我正在谈论的关闭协议的一些示例:
IObjectWithSite.SetSite(null)IOleObject.SetClientSite(null)IOleObject.Close()IDTExtensibility2.OnDisconnectionIDTExtensibility2.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.