Вам необходимо хорошо понимать Runtime Callable Wrapper , чтобы использовать COM с .Net. По сути, все, что у вас есть в вашем .Net-коде, которое является ссылкой на COM-объект, на самом деле является ссылкой на RCW. RCW управляет счетчиком ссылок на базовый COM-объект, подсчитывая, сколько ссылок на него, и когда количество ссылок на него падает до 0, он вызовет Release
(один раз) для базового объекта. Пока RCW активен, он будет поддерживать единственную ссылку на объект COM.
API ReleaseComObject
уменьшит счетчик ссылок на RCW на 1. Если это приведет к счетчику ссылок на RCW к 0, тогда RCW вызовет Release
для объекта COM, в противном случае - нет. Существует также FinalReleaseComObject
, который заставит счетчик ссылок на RCW перейти к 0 (таким образом, вызовет RCW Release
), хотя это довольно рискованно, если у вас есть другие выдающиеся ссылки на RCW, так как они, вероятно, приведут к ошибке .
«Обычно», ссылки на RCW управляются, когда объекты, на которые есть ссылка на него, являются сборщиком мусора - это объясняет, почему вы увидели, что COM-объект был освобожден, когда вы принудительно собрали сборщик мусора. Это, в сочетании с тем, что мы знаем о том, как работает RCW, говорит нам о том, что на RCW были и другие ссылки, которые вам также «понадобились бы» для вызова ReleaseComObject
, чтобы вызвать его на Release
.
Вызов ReleaseComObject
является своего рода завершением работы среды выполнения .Net, и вы должны быть очень осторожны, чтобы управлять всеми созданными ссылками. Некоторые из созданных ссылок являются «неявными» ссылками - они возникают из-за таких действий, как вызов свойств, которые возвращают ссылки, которые вы затем вызываете. Иногда это называют проблемой «слишком много точек», когда вы делаете что-то вроде этого:
object.foo.blah.baz.something()
"foo", "blah" и "baz", вероятно, являются ссылками на некоторый COM-объект, о котором вам нужно подумать.