C# 为什么';t Marshal.Release调用释放我的COM对象?

C# 为什么';t Marshal.Release调用释放我的COM对象?,c#,.net,com,interop,C#,.net,Com,Interop,我已经阅读了的文档,上面写着: 完成指针操作后,始终使用Marshal.Release减少引用计数 我通过.NET使用COM对象编写了一个测试解决方案,我发现在使用COM对象时,既不调用COM对象的Marshal.getIUnknownProbject也不调用Marshal.Release方法,导致调用COM对象的AddRef或Release方法 这是怎么回事?的Marshal.AddRef和Marshal.Release方法调用COM实例的COM AddRef和Release方法Marshal

我已经阅读了的文档,上面写着:

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

我通过.NET使用COM对象编写了一个测试解决方案,我发现在使用COM对象时,既不调用COM对象的
Marshal.getIUnknownProbject
也不调用
Marshal.Release
方法,导致调用COM对象的
AddRef
Release
方法


这是怎么回事?

Marshal.AddRef
Marshal.Release
方法调用COM实例的COM AddRef和Release方法
Marshal.getIUnknownfobject
可能正在调用,这意味着返回的
IUnknown
指针上有一个
AddRef


可能您的测试项目存在某种缺陷,可能在另一个COM实例上调用AddRef和Remove,而不是您期望的实例?

the
Marshal.AddRef
Marshal.Release
方法正在调用COM实例的COM AddRef和Release方法
Marshal.getIUnknownfobject
可能正在调用,这意味着返回的
IUnknown
指针上有一个
AddRef


也许您的测试项目存在某种缺陷,可能在另一个COM实例上调用AddRef和Remove,而不是您期望的实例?

等等,我想我已经找到了。您正在创建一个COM对象,然后在该COM对象周围创建一个运行时可调用包装器,然后向运行时可调用包装器请求其朋克,然后您想知道为什么在该朋克上调用release不会调用您的release?这是你的问题的总结吗

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

那么,为什么你认为它会叫你释放?它将调用运行时可调用包装的发行版。包装器包装您的对象;这就是为什么它被称为包装器。运行时可调用包装器不需要每次添加并释放对象时都添加并释放它!为什么会这样?它需要让你的对象保持活动状态,并且它已经在你的对象上有了一个ref;这足以使包装对象保持活动状态。为什么要做不必要的工作

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

这样想吧。假设你说:

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

abc->def = foo;
foo->AddRef();
这为foo添加了一个ref。它会给废话添加一个参考吗?当然不是。为什么会这样?foo有一个参考号来指这些废话;事实上,美国广播公司(abc)让福活了下来,这与废话无关

这里也一样。你有:

wrapper = new RCW();
wrapper->wrapped = yourobject;
yourobject->AddRef();
这会向对象添加一个引用。现在如果你有

wrapper->QI(IUnknown, &punk)
这并没有给你底层对象的朋克,而是给你包装器的朋克。如果你说

punk->AddRef();

它不会添加底层对象,而是添加包装器

等一下,我想我找到了。您正在创建一个COM对象,然后在该COM对象周围创建一个运行时可调用包装器,然后向运行时可调用包装器请求其朋克,然后您想知道为什么在该朋克上调用release不会调用您的release?这是你的问题的总结吗

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

那么,为什么你认为它会叫你释放?它将调用运行时可调用包装的发行版。包装器包装您的对象;这就是为什么它被称为包装器。运行时可调用包装器不需要每次添加并释放对象时都添加并释放它!为什么会这样?它需要让你的对象保持活动状态,并且它已经在你的对象上有了一个ref;这足以使包装对象保持活动状态。为什么要做不必要的工作

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

这样想吧。假设你说:

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

abc->def = foo;
foo->AddRef();
这为foo添加了一个ref。它会给废话添加一个参考吗?当然不是。为什么会这样?foo有一个参考号来指这些废话;事实上,美国广播公司(abc)让福活了下来,这与废话无关

这里也一样。你有:

wrapper = new RCW();
wrapper->wrapped = yourobject;
yourobject->AddRef();
这会向对象添加一个引用。现在如果你有

wrapper->QI(IUnknown, &punk)
这并没有给你底层对象的朋克,而是给你包装器的朋克。如果你说

punk->AddRef();

它不会添加底层对象,而是添加包装器

你能提供示例代码吗?这个问题对我来说毫无意义。Marshal.getiunknownfobject是用来让朋克访问托管对象的,那么您所说的“我的COM对象”是什么呢?它不是addref您的COM对象,而是addref运行时的托管对象。你能更详细地解释一下你想在这里做什么吗?更新问题为clearer@EricLippert,如果参考计数属于RCW,那么为什么要调用
封送.Release
而不是
封送.ReleaseCOMObject
?您能提供示例代码吗?这个问题对我来说毫无意义。Marshal.getiunknownfobject是用来让朋克访问托管对象的,那么您所说的“我的COM对象”是什么呢?它不是addref您的COM对象,而是addref运行时的托管对象