This post originated from an RSS feed registered with .NET Buzz
by Sam Gentile.
Original Post: To ReleaseComObject or Not?
Feed Title: Sam Gentile's Blog
Feed URL: http://samgentile.com/blog/Rss.aspx
Feed Description: .NET and Software Development from an experienced perspective - .NET/CLR, Rotor, Interop, MC+/C++, COM+, ES, Mac OS X, Extreme Programming and More!
Andrew Whitechapel, from the Office team has been posting on RCO Woes and now has a pretty extensive post on when you should and when you can safely call RCO from Office Add-Ins. I can't speak for Office Add-ins but I have had extyensive run-ins with RCO everywhere else-) He notes in his comments to mine, “Sam has clearly been wrestling with this beast for a long time, and has evolved some workable strategies for dealing with the problems. I suppose the basic problem is that .NET moved to a more convenient memory managed world, while COM still inhabits a roll-your-own lifetime management world. Finding a suitable enzyme that will completely bind to both worlds is non-trivial. Sam, do you have any further insights? Perhaps you could provide some details of your wrapper solution? I'm sure lots of folk would be interested to see what you've done there.“
Yes I can. Yes, the fundamental issue is always going to be this mismatch between the GC environment of the CLR and the COM roll-you-own-lifetime management world as discussed extensively in my MSDN article which details all the many differences between the two worlds. My posts over the last two years or so have documented my frustrations with the RCW not being all it could and should have been to evolving workable strategies going forward. As I discussed with Chris Bruume and eventually Sonja and crew, there is very considerable customer pain and bleeding in this area. As I mentioned in my answer to Chris, it's not that RCO doesn't solve many (but not all) of the issues, it's that it's usage is extremely awkward and begins to polluter your nice business logic code base with these ugly RCO calls all over the place. How extensive is this usage pattern? In my experience over the last 4 years with this area, it has come up in 100% of my customer scenarios. Leaving it to chance only works for the bare simplest COM components that are perhaps MSDN samples and in my experience, does not work in production COM code. Andrew lists:
1 Under what circumstances would you want/need to RCO? 1.1 When your RCW is proxying a COM object that’s holding onto a lot of memory or other resource that you need to release eagerly (for performance or contention reasons). 1.2 When you believe a circular reference has deadlocked and you want to break the cycle. 1.3 When your RCW’s Finalize is in a race with the CLR’s shutdown and you’re in danger of orphaning a COM interface pointer. 1.4 When you have < 100% confidence that either your own code or some other code that you’re talking to isn’t cleaning up correctly in some corner case Hmmm…- does anyone let this kind of software out the door? (a rhetorical question).
2 Under what circumstances could you safely RCO? 2.1 Q: What would be the scope of any collateral damage? A: anything in the AppDomain. So, where are the AppDomains in your scenario
I agree with all that but it seams like 1.1 and 1.3 happen pretty easily in production COM systems. The move in Whidbey to give the GC a much stronger hint with memory pressure is a huge step in getting the CLR GC aware that I am holding on to a huge chunk of unmanaged memory that you don't know about. However, this mechanism is not currently available for the RCW and COM Interop case. For now, what I evolved back in 2002, together with Paresh and others at Groove when we dealt with huge amounts of this, is to write wrapper classes to abstract away the RCO calls and implement IDisposable away from the “regular” code. Paresh does show the implementation of wrappers with two different alternatives here so I won't recopy it. However, there are still tricky issues that I mention at the bottom of this post. It's a hard problem and right now we all have to live with the fact that for Interop code we will have to do a lot of RCO and do it in safe contexts but we can at least move to patterns of wrappers which perhaps could be code generated - hey that's an idea for an add-in for me!