.NET and COM Interoperability : release COM from .NET client
Assume I have a COM object (unmanaged) and .NET Client.
Is it necessary to call from the .NET client Marshal.FinalReleaseComObject
method in order to release the COM object?
No. There is no need to explicitly release a COM object from a .Net client. The COM object will be collected like any other .Net object and will release it's underlying native handle once all references to it are removed.
Explicit use of FinalReleaseComObject
can actually lead to programming errors. If another component in your code is still referencing the COM object you will be yanking out the native object out from under it. That will possibly lead to runtime failures down the road.
A modified "Yes", and a "No".
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 :
ReleaseComObject
, but not FinalReleaseComObject
, 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. 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.)
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).
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.)
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.
Happy coding.
链接地址: http://www.djcxy.com/p/58212.html上一篇: 两个sql用于排序时间戳日期