A изменено"Да" и "Нет".
Прежде всего, имейте в виду, что ReleaseComObject
не автоматически уменьшает реальный счетчик объектов COM. Скорее это уменьшает внутренний счетчик RCW. (Каждый раз, когда тот же COM-объект перемещается из COM-> NET, он будет использовать тот же RCW и увеличивать счетчик RCW на единицу.) Аналогичным образом, FinalRelaseComObject
также влияет на RCW эффективно противостоит "устанавливает его в 0". Когда счетчик RCW обнулится, .NET уменьшит фактический COM ref-count.
Итак, «да», но изменено для этих правил :
- Каждый раз, когда объект пересекается с COM-> NET, он должен иметь
ReleaseComObject
, , но не FinalReleaseComObject
, вызванный на него. То есть он должен вызываться один раз каждый раз, когда объект пересекается, , даже если это приводит к RCW .
- Количество ссылок на RCW (который является просто прокси-оберткой) не имеет значения; только когда объект пересек границу. Смотрите правило № 1. (Важно контролировать ссылки и кто их хранит, но «худшее», что происходит в этом случае, является исключением из использования «отдельного RCW», которое ничем не отличается от , чем использование потока Disposed.)
Я говорю приведенные выше правила, а не FinalReleaseComObject
, поскольку объекты RCW кэшируются в прокси-сервере идентификации, поэтому с использованием FinalReleaseComObject
повлияет на COM-> NET пересечения границ даже не знал о ! (Это плохо, и на данный момент я полностью согласен с ответом JaredPars.)
И «нет» в этом, когда RCW будет освобожден (вызывается финализатор), он автоматически «освободит» ссылку COM (фактически вызов FinalReleaseComObject
включен сам). Помните, что, поскольку существует только один объект RCW, это означает, что он никогда не будет возвращен, пока есть ссылка на него в .NET. Если RCW исправлен, то нет проблем , потому что сверху нет больше ссылок на упомянутое RCW, и поэтому .NET знает, что он может уменьшить счетчик ссылок COM на единицу (что может вызвать COM-объект) быть уничтоженным).
Однако, поскольку .NET GC является привередливым и недетерминированным , использование этого поведения означает, что время жизни объекта не контролируется. Это может вызвать, например, множество тонких проблем при работе с объектной моделью Outlook. (Он может быть менее подвержен проблемам с другими COM-серверами, но OOM выполняет забавное внутреннее «кеширование» объектов. Легко получить исключение «Элемент уже изменен», если явно не контролировать время жизни.)
В моем коде у меня есть класс ComWrapper
, который поддерживает IDisposable
. Это позволяет мне передавать объекты RCW, полученные из COM-> NET с чистым сроком владения . После перехода на этот подход у меня было очень мало проблем (на самом деле их практически не было) после перехода на этот подход и многочисленных проблем до этого. Недостатком является то, что необходимо определить границу COM-> NET, но если это так, то внутренне все времена жизни правильно обрабатываются.
Удачного кодирования.