.NET and COM Interoperability : release COM from .NET client(.NET 和 COM 互操作性:从 .NET 客户端释放 COM)
问题描述
假设我有一个 COM 对象(非托管)和 .NET 客户端.
Assume I have a COM object (unmanaged) and .NET Client.
是否需要从 .NET 客户端调用 Marshal.FinalReleaseComObject
方法才能释放 COM 对象?
Is it necessary to call from the .NET client Marshal.FinalReleaseComObject
method in order to release the COM object?
推荐答案
修改是"和否".
首先,请记住 ReleaseComObject
不会自动减少真正的 COM 对象引用计数.相反,它会减少内部 RCW 计数器.(每次 same COM 对象从 COM->NET 移出时,它都会使用 same RCW 并将 RCW 计数器加一.)同样,FinalRelaseComObject
也会影响 RCW 计数器并有效地将其设置为 0".当 RCW 计数器变为零时,.NET 将减少 actual COM ref-count.
First off, bear in mind that ReleaseComObject
does not automatically decrease the real COM object ref-count. Rather it decreases the internal RCW counter. (Every time the same COM object is moved from COM->NET it will use the same RCW and increment the RCW counter by one.) Likewise, FinalRelaseComObject
also affects the RCW counterand effectively "sets it to 0". It is when the RCW counter goes to zero that .NET will decrease the actual COM ref-count.
所以,是",但根据这些规则进行了修改:
So, "yes", but modified for these rules:
- 每次一个对象从 COM->NET 交叉它应该有
ReleaseComObject
,但不是FinalReleaseComObject
,对其进行调用.也就是说,每次对象交叉时都应该调用它一次,即使它导致引用等于 RCW. - 对 RCW(只是一个代理包装器)的引用数量无关紧要;只有物体越过边界的次数.参见规则#1.(控制引用和谁保留它们很重要,但在这种情况下发生的最坏情况"是使用分离的 RCW"的一个例外,这与使用 Disposed 流没有什么不同.)
- Every time an object cross from COM->NET it should have
ReleaseComObject
, but notFinalReleaseComObject
, invoked upon it. That is, it should be invoked once for each time the object crosses, even if it results in a reference-equals RCW. - The number of references to the RCW (which is just a proxy wrapper) do not matter; only the times the object has crossed the boundary. See rule #1. (It is important to control references and who keeps them, but the "worst" that happens in this case is an exception from using a "detached RCW" which is no different than using a Disposed stream.)
我说上面的规则和不是 FinalReleaseComObject
因为RCW对象缓存在一个身份代理中,所以使用FinalReleaseComObject
会影响你甚至不知道的 COM->NET 边界交叉!(这很糟糕,在这一点上,我完全同意 JaredPars 的回答.)
I say the rules above and not FinalReleaseComObject
because the RCW objects are cached in an identity proxy, so using FinalReleaseComObject
will affect COM->NET boundary crossings you didn't even know about! (This is bad and, on this point, I entirely agree with JaredPars answer.)
而否",当一个RCW被回收时(终结器被调用),它会自动释放"COM引用(有效地调用FinalReleaseComObject
本身).请记住,由于只有一个 RCW 对象,这意味着只要在 .NET 中有对它的引用,它就永远不会被回收.如果回收 RCW,则 没有问题,因为从上面看,不再有对所述 RCW 的引用,因此 .NET 知道它可以将 COM 引用计数减少一(这可能会导致 COM要销毁的对象).
And "no" in that, when an RCW is reclaimed (the finalizer is called), it will automatically "release" the COM reference (effectively call FinalReleaseComObject
on itself). Remember that since there is only one RCW object this means that it will never be reclaimed as long as there is a reference to it in .NET. If the RCW is reclaimed there is no problem because, from above, there are no more references to said RCW and thus .NET knows it can decrease the COM ref-count by one (which may cause the COM object to be destroyed).
但是,由于 .NET GC 是挑剔的且非确定性,因此依赖此行为意味着对象的生命周期不受控制.例如,在使用 Outlook 对象模型时,这可能会导致许多微妙的问题.(其他 COM 服务器可能不太容易出现问题,但 OOM 会在内部对对象进行有趣的缓存".如果不明确控制生命周期,很容易得到项目已被修改"异常.)
However, since the .NET GC is finicky and non-deterministic, relying on this behavior means that object-lifetimes are not controlled. This can cause many subtle issues when working with the Outlook Object Model, for instance. (It may be less prone to issues with other COM servers, but the OOM does funny "caching" of objects internally. It is easy to get a "Item has already been modified" exception when not controlling lifetimes explicitly.)
在我的代码中,我有一个支持 IDisposable
的 ComWrapper
类.这使我可以传递从 COM->NET 获得的具有明确生命周期所有权的 RCW 对象.在切换到这种方法后,我在 Outlook-Addin 开发中遇到的问题非常少(实际上几乎没有),并且之前有许多问题.缺点"是需要确定 COM->NET 边界,但一旦确定,那么内部所有生命周期都得到正确处理.
In my code I have a ComWrapper
class that supports IDisposable
. This allows me to pass around RCW objects obtained from the COM->NET with clear lifetime ownership. I have had very few issues (almost none, actually) in my Outlook-Addin development after switching to this approach and numerous issues before hand. The "downside" is that COM->NET boundary needs to be determined, but once that is, then internally all the lifetimes are correctly handled.
编码愉快.
这篇关于.NET 和 COM 互操作性:从 .NET 客户端释放 COM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:.NET 和 COM 互操作性:从 .NET 客户端释放 COM
基础教程推荐
- SSE 浮点算术是否可重现? 2022-01-01
- 为什么Flurl.Http DownloadFileAsync/Http客户端GetAsync需要 2022-09-30
- MS Visual Studio .NET 的替代品 2022-01-01
- 将 XML 转换为通用列表 2022-01-01
- c# Math.Sqrt 实现 2022-01-01
- 将 Office 安装到 Windows 容器 (servercore:ltsc2019) 失败,错误代码为 17002 2022-01-01
- 有没有办法忽略 2GB 文件上传的 maxRequestLength 限制? 2022-01-01
- 如何在 IDE 中获取 Xamarin Studio C# 输出? 2022-01-01
- rabbitmq 的 REST API 2022-01-01
- 如何激活MC67中的红灯 2022-01-01