COM互操作引用计数指南

COM互操作引用计数指南,com,interop,Com,Interop,最近,我花了相当多的时间编写各种VisualStudio扩展项目。即使项目都是托管代码,以访问核心VS服务,但仍然需要使用旧式COM接口 以下是一个例子: var selectionTracker = (IVsMonitorSelection)serviceProvider.GetService(typeof(SVsShellMonitorSelection)); IntPtr ppHier; uint pitemid; IVsMultiItemSelect ppMIS; IntPtr ppSC

最近,我花了相当多的时间编写各种VisualStudio扩展项目。即使项目都是托管代码,以访问核心VS服务,但仍然需要使用旧式COM接口

以下是一个例子:

var selectionTracker = (IVsMonitorSelection)serviceProvider.GetService(typeof(SVsShellMonitorSelection));
IntPtr ppHier;
uint pitemid;
IVsMultiItemSelect ppMIS;
IntPtr ppSC;
selectionTracker.GetCurrentSelection(out ppHier, out pitemid, out ppMIS, out ppSC)))
如您所见,此调用返回2个指针(ppHier和ppSC)和一个对象ppMIS。 问题是:我应该如何在COM引用计数方面做得更好

我的理解是,在COM世界中,当一个方法返回一个指向对象的指针时,这个指针在返回之前就被添加了。这意味着为了防止COM对象泄漏,我必须在使用完COM对象后释放它们

我还假设我作为一个对象得到的东西已经被包装到一个RCW中,当它最终确定时,RCW将负责引用的发布

应用于上述调用的这两个假设意味着我必须确保在我的两个指针上调用'Marshal.Release',但我不应该对返回的对象的引用计数做任何事情


换言之,我的问题是:假设我使用的COM对象是按照COM规则玩的,那么上面的方法是处理COM引用计数的正确方法吗?

在这个特定场景中,您需要调用IntPtr变量的Marshal.Release,否则它们不会消失。当然,如果您告诉封送处理程序直接使用对象(或特定类型),那么您就不必担心它,因为RCW将确保在将来某个时候(即在垃圾收集过程中调用终结器时)销毁该对象

当然,终结器方法可能发生在不确定的时间点,因此,如果对象维护一些您需要删除的资源,理想情况下,您应该在包装器为您进行释放之前调用Marshal.ReleaseComObject以减少其引用计数