До недавнего времени я полагал, что время выполнения.NET только увеличивает подсчет ссылок COM-объектов на 1 при создании обертки вызовов среды выполнения, и что только одна такая обертка вызовов среды выполнения создается для любого данного COM-объекта.
Если я не ошибаюсь, вышеупомянутое подразумевает того Маршала. FinalReleaseComObject и Маршал. ReleaseComObject делают то же самое на практике.
Однако сегодня я писал некоторые тесты, чтобы проверить, что COM-объекты правильно выпущены моим кодом. Я делаю это путем вызова, предположительно, выпущенного объекта и проверки на ожидаемый InvalidComObjectException
. Оказывается, что существуют случаи, где исключение выдается после a FinalReleaseComObject
, но не после a ReleaseComObject
.
Это означает, что.NET 2,0 времени выполнения может содержать больше чем одну ссылку на COM-объект? Если так, когда это делает это?
Здесь есть дополнительный уровень косвенного обращения. Да, RCW ведет единичный счетчик ссылок на указатели собственного COM-интерфейса.Но у RCW также есть счетчик ссылок, он увеличивается каждый раз, когда указатель интерфейса COM отображается на RCW. Что может произойти, если метод COM возвращает указатель на интерфейс. Финализатор соответствующего класса-оболочки .NET уменьшает его.
Вы можете повозиться с этим счетчиком ссылок непосредственно через Marshal.ReleaseComObject (), который уменьшает его на единицу, как это делает финализатор, и Marshal.FinalReleaseComObject (), который обнуляет его, гарантируя, что IUnknown :: Release () вызывается метод. Они, конечно, попадают в категорию «лучше знай, что делаешь». Если ошибиться, возникает уродливое и не поддающееся отладке исключение «COM-объект, отделенный от лежащего в его основе RCW».