7

.NET 3.5 C#WinFormsアプリケーションに、5つのメソッドを持つクラスがあります。各メソッドは、C++COMインターフェイスの異なるセットを使用します。Marshal.FinalReleaseCOMObjectこれらのCOMオブジェクトのクリーンアップに使用しています。このコードは、この.NETプラットフォームで問題なく正常に機能します。ICOMInterface1しかし、このアプリケーションを.NET 4.0に移動すると、変数をからにキャストした行で、これらのメソッドの1つでこのエラーが発生し始めますICOMInterface2

ICOMInterface1  myVar= obj as ICOMInterface2; 

基になるRCWから分離されたCOMオブジェクトは使用できません。

また、を使用している行を削除してMarshal.FinalReleaseCOMObjectも、このエラーは発生しません。

ここで何が欠けていますか?また、これらのアンマネージCOMオブジェクトを.NET 4.0プラットフォームのメモリからクリーンアップするにはどうすればよいですか?

4

1 に答える 1

14

The simple answer is to never use Marshal.FinalReleaseComObject unless you absolutely must. And if you do, there are some additional rules you must follow.

When a COM object is used in .NET, the runtime creates what's known as a "RCW" or "runtime callable wrapper" for that object. This RCW is just a normal object that holds a COM reference on the object. When this object is garbage collected, it will call IUnknown::Release() on the COM object, as you'd expect. What this means is unless your COM object requires that the last Release() is done at a very certain moment in time, just let the garbage collector take care of it. Many COM objects fall into this case, so absolutely verify that you must manage the call to Release() carefully.

So when you're calling FinalReleaseComObject, that is essentially decrementing the reference the RCW has on the COM object until it hits zero and the RCW then releases the COM object. At this point, this RCW is now zombied, and any use of it will give the exception you've seen. The CLR (by default) only creates a single RCW for any underlying COM object, so this means if the COM API you're using returned the same object twice, it's just going to have a single RCW. Calling FinalReleaseComObjectwould mean that suddenly all uses of that RCW are toast.

The only way to guarantee you have a unique Marshal.GetUniqueObjectForIUnknown, which prevents any RCW sharing. But like I said earlier, in most COM APIs this isn't neccessary to do in the first place, so just don't do it.

Paul Harrington wrote up a good blog post about [Final]ReleaseComObject and it's evils. It's a dangerous weapon that unless needed will only hurt you. Since you're asking this question, I'd suspect you don't actually need to be calling it at all. :-)

于 2012-04-11T16:30:20.610 に答える