为什么不Marshal。请在我的COM对象上调用Release?

时间:2010-12-23 22:08:12

标签: c# .net com interop

我已阅读Marshal.GetIUnknownForObject的文档,并说:

  

完成指针后,始终使用Marshal.Release减少引用计数。

我用一个COM对象编写了一个测试解决方案,我通过.NET使用它,我发现当使用wrapper到我的COM对象时,Marshal.GetIUnknownForObjectMarshal.Release都不会导致{我的COM对象的{1}}或AddRef方法被调用。

这是怎么回事?

2 个答案:

答案 0 :(得分:6)

等一下,我想我已经明白了。你正在制作一个COM对象,然后你围绕那个COM对象制作一个运行时可调用的包装器,然后你要求运行时可调用的包装器为它的朋克,然后你想知道为什么在那个朋克上调用release不会调用你的发布?这总结了你的问题吗?

如果是这样,你可能已经在问题中提到了所有这些细节,而不是让我们猜测。

那么,为什么你认为它会调用你的版本?它将调用运行时可调用包装器的Release 。包装器包装您的对象;这就是为什么它叫做包装。运行时可调用包装器不会需要来addref并在每次被添加并释放时释放您的对象!为什么会这样?它需要让你的对象保持活着,它已经在你的对象上有一个引用;这足以使包裹的物体保持活力。为什么不必要的工作?

当你在COM对象周围有一个运行时可调用包装器时,你应该合理地期望对象的ref计数在对象的整个生命周期内是不变的。运行时接受一次ref,当RCW最后一次被垃圾收集或以其他方式释放时,它会释放ref并且对象会自行删除。

这样想。假设你说:

foo->bar = blah;
blah->AddRef();

blah得到addref'd,因为foo-> bar有一个对它的引用。现在你说:

abc->def = foo;
foo->AddRef();

这为foo添加了一个参考。它是否添加了参考等等?当然不是。为什么会这样? foo有一个基础; foo被abc保持活着的事实与blah无关。

这里也是一样的。你有:

wrapper = new RCW();
wrapper->wrapped = yourobject;
yourobject->AddRef();

这为你提供了一个参考资料。现在,如果你有

wrapper->QI(IUnknown, &punk)

它不会给你底层对象的朋克,它会给你包装器的朋克。如果你说

punk->AddRef();

没有addref底层对象,它addrefs包装器。

答案 1 :(得分:3)

Marshal.AddRefMarshal.Release方法正在调用COM实例的COM AddRef和Release方法; Marshal.GetIUnknownForObject可能会调用QueryInterface,这意味着返回的AddRef指针上有IUnknown

也许你的测试项目有点错误,可能在另一个COM实例上调用AddRef和Remove而不是你想要的那个?