Of course, .NET COM interop has this fascinating simple story. We'll give you these wonderfull wrapper objects, that will give COM the illusion that they are interacting with other COM objects and give .NET objects the illusion that they're interacting with other .NET objects. The story is that you supply your COM Type Libraryto tlbimp.exe and it spits out this wonderfull Runtime Callable Wrapper (RCW). The counterpart on the otherside is COM-callable wrapper.
Its a good story in theory. The wrappers handle all the transitions between managed and unmanaged code and all the issues between the world of COM and the world of .NET like data marshalling, exception handling, object lifetime. The issue is that to play in the .NET world, the RCW's lifetime is controlled by the CLR's garbage collector. Each RCW caches its interface pointers for the COM object that it wraps, and internally performs reference counting on these interface pointers. When an RCW is collected, it's finalizer calls IUnknown.Release on all its cached interface pointers. Thus, a COM object is guaranteed to be alive as long as its RCW is alive.
Herein lies the problem for non-trivial COM components and large interacting COM components in a large COM infrastructure. The release calls are non-determinstic in the sense that they will happen when the GC gets around to killing off the RCW. Most particuarly,this plays havoc witth COM architectures that reley on Callbacks happening between COM components with their own sense of when they want to be released. The wrapped COM object doesn't get released until the RCW is collected. Oh sure, Interop has a way for you to "insist", again in theory. You can call the Marshal::ReleaseComObject method in the System::Runtime::InteropServices namespace. And you can call raw release calls that are provided. The point is that in a non-trivial COM architecture with callabacks and such, this becomes a mess and is quite problematic. In my work in this area for a certain company, we have had over a month's worth of problems with crashes and leaks and having to do countless "Tweaks" to call ReleaseComObject and raw releases. It comes down to this: It shouldn't be this dran hard! The COM Interop layer should be handling all of this INSIDEits wrapper in a determinstic way. I'm beginning to wonder if its design is flawed.
8:35:18 AM
|
|