Console Apps and STA COM Objects

This article assumes that you have basic knowledge of COM and apartments. 

I've talked with several people who found that COM objects they created in their console applications were not destroyed until the application exited.  This was causing memory leaks and errors in their apps.  Further investigation found that they were using STA COM objects and were depending on the Garbage Collector to clean up after them.  Even adding explicit calls to GC::Collect() did not solve their problem. 

The problem is occuring due to the nature of the CLR and GC.  In this case the COM objects are destroyed during Garbage Collection.  Remember finalization occurs on a background thread.  When the RCW is aksed to destroy itself on the background thread, the CLR correctly uses a COM proxy to comunicate with the COM object since the object lives in a different COM apartment.  So a message is added to the Main thread to Release the COM object. 

But this is a Console application so no message pumping occurs!!!  Hence the objects are never collected. 

This problem can be fixed in several ways. 

1) Pump :)  Simply call System.Windows.Forms.Application.DoEvents() periodically to ensure that COM objects have a chance to release. 

2) Use Marshal.ReleaseComObject() instead of waiting for the GC.  Since the call occurs in the same apartment, no proxy is needed and the object can finalize as if you called Release.  Note: Make sure you understand all of the implications of this method before you use it.