I am working on an Outlook Addin where I create a lot of COM objects(Outlook mail, Outlook folder etc). My understanding is that since these objects are COM objects,CLR won't release memory from these objects and i'll have to take care of releasing memory from these objects.So to release memory from these object I use
Marshal.ReleaseComObject(Object);
But unfortunately this doesn't seem to work.Then I put a GC.Collect() statement after Marshal.ReleaseComObject(Object);and this worked.I didn't get any memory related exception after that.
My question is that if CLR can relase memory from COM objects, why it doesn't do it by itself. and if it can't then how GC.Collect() statement worked in my case.
Best Answer
You need to have a good understanding of the Runtime Callable Wrapper in order to use COM with .Net. Basically, everything you have in your .Net code that is a reference to a COM object, is really a reference to an RCW. The RCW manages the reference count on the underlying COM object by counting how many references are to it, and when the reference count on it drops to 0, it will call
Release
(once) on the underlying object. While the RCW is live, it will maintain a single reference on the COM object.The
ReleaseComObject
API will decrease the reference count on the RCW by 1. If this brings the reference count on the RCW to 0, then the RCW will callRelease
on the COM object, otherwise not. There is alsoFinalReleaseComObject
which will cause the reference count on the RCW to go to 0 (thus cause the RCW to callRelease
) although this is kind of risky if you have other references outstanding on the RCW as they will probably error."Normally", the references on the RCW are managed when the objects which have a reference to it are garbage collected - this would explain why you saw the COM object be released when you forced the garbage collection. This, combined with what we know about how the RCW works tells us that there were other references on the RCW that you also would have "needed" to call
ReleaseComObject
on in order to cause it toRelease
.Calling
ReleaseComObject
is kind of an end run around the .Net runtime, and you have to be super careful to manage all of the references that are created. Some of the references that are created are "implicit" references - these come about because of doing things like calling into properties which return references which you then call in on. This is sometimes refered to as the "too many dots" problem, when you do something like this:The "foo", "blah" and "baz" are probably all references to some COM object somewhere that you need to think about.