Frage

Bis vor kurzem glaubte ich, dass die .NET-Laufzeit erhöht nur den Referenzzähler von COM-Objekten von 1, wenn ein Runtime-Callable Wrapper , und dass nur eine solche Laufzeit aufrufbare Wrapper wird für einen bestimmten COM-Objekt erstellt.

Wenn ich mich nicht irre, impliziert die obige, dass Marshal.FinalReleaseComObject und Marshal.ReleaseComObject die gleiche Sache in der Praxis tun.

Heute jedoch war ich einige Tests zu schreiben, dass COM-Objekte überprüfen ordnungsgemäß durch meinen Code freigegeben. Ich tue dies, indem die angeblich freigegeben Objekt aufgerufen wird und für die erwartete InvalidComObjectException überprüfen. Es stellt sich heraus, dass es Fälle gibt, in denen die Ausnahme nach einem FinalReleaseComObject geworfen wird, aber nicht nach einem ReleaseComObject.

Bedeutet dies, dass die .NET 2.0 Runtime mehr als einen Verweis auf ein COM-Objekt halten können? Wenn ja, wann wird es das tun?

War es hilfreich?

Lösung

Es gibt eine zusätzliche Dereferenzierungsebene hier. Ja, hält die RCW eine einzige Referenzzählung auf den nativen COM-Schnittstelle Zeiger. Aber die RCW hat auch einen Referenzzähler, es jedes Mal, wenn ein COM-Interface-Zeiger erhöht wird, wird die RCW abgebildet. Was passieren kann, wenn ein COM-Methode einen Schnittstellenzeiger zurückgibt. Die Finalizerthread der entsprechenden .NET-Wrapper-Klasse dekrementiert.

Sie können mit dieser Referenz bastele direkt durch Marshal.ReleaseComObject () zählen, die sie von einem dekrementiert wie der Finalizerthread tut, und Marshal.FinalReleaseComObject (), die er auf Null zappt, die gewährleisten, dass die IUnknown :: Release () Methode aufgerufen wird. Sie natürlich fallen in die „besser wissen, was du tust“ -Kategorie. Immer es produziert falsch das hässliche und undebuggable Ausnahme „COM-Objekt vom zugrunde liegenden RCW getrennt“.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top