2012-03-14 7 views
7

Предположим, у меня есть COM-объект (неуправляемый) и .NET Client.Интеграция .NET и COM: выпуск COM из .NET-клиента

Нужно ли позвонить из .NET-клиента Marshal.FinalReleaseComObject, чтобы освободить COM-объект?

+3

http://blogs.msdn.com/b/visualstudio/archive/2010/03/01/marshal-releasecomobject-considered-dangerous.aspx –

+0

Спасибо - очень полезная статья –

ответ

2

Нет. Нет необходимости явно освобождать объект COM от клиента .Net. COM-объект будет собран, как и любой другой .Net-объект, и будет выпущен его основной дескриптор, когда все ссылки на него будут удалены.

Явное использование FinalReleaseComObject может фактически привести к ошибкам программирования. Если другой компонент вашего кода все еще ссылается на объект COM, вы будете вытаскивать из него собственный объект. Это, возможно, приведет к сбоям во время работы в будущем.

+0

Хотя «теоретически» может быть нет потребность, «на практике», там * определенно есть *. Кроме того, не используйте FinalReleaseComObject, а скорее ReleaseComObject для * каждый раз, когда любой COM-объект был перенесен на границу COM.NET. Я программирую Outlook Addin: я могу сказать, что предоставление объектов * явное время жизни - единственный способ создать рабочую надстройку *. Период. (Я использую класс helper/wrapper, который поддерживает Dispose, я использую 'use'.) –

+3

Неправильная практика. Вы GC.Collect() + GC.WaitForPendingFinalizers(), если вам нужно, никогда не ошибаетесь. –

+1

@HansPassant Это не работает с объектной моделью Outlook. Различные связанные «решения» включают попытку вызывать эту последовательность * дважды * подряд. Он просто не работает «на практике» (в тех случаях, когда я занимаюсь). –

2

A изменен «Да» и «Нет».

Прежде всего, имейте в виду, что ReleaseComObjectне автоматически уменьшает реальный COM-объект ref-count. Скорее он уменьшает внутренний счетчик RCW. (Каждый раз, когда тот же объект COM перемещается из COM-> NET, он будет использовать тот же RCW и увеличивать счетчик RCW на единицу.) Аналогично, FinalRelaseComObject также влияет на счетчик RCW, эффективно «устанавливает его на 0». Это когда счетчик RCW обращается в ноль, что .NET будет уменьшать значение COM ref-count.

Так, "да", но модифицирована для этих правил:

  1. Каждый раз, когда объект крест из COM-> NET он должен иметь ReleaseComObject, но неFinalReleaseComObject , ссылается на него. То есть, он должен быть вызван один раз за каждый раз, когда объект пересекает, , даже если он приводит к эталонному значению RCW.
  2. Число ссылок на RCW (это просто прокси-обертка) не имеет значения; только время, когда объект пересек границу. См. Правило №1. (Это очень важно контролировать ссылки и кто держит их, но «худшее», что происходит в этом случае является исключением из использования «отстраненную RCW», который не является не отличается, чем при использовании Disposed потока.)

Я говорю правила выше и неFinalReleaseComObject, так как объекты RCW кэшируются в прокси идентичности, так с помощью FinalReleaseComObjectбудет влиять COM-> NET граничные переходы вы даже не знаете о! (Это плохо и, на данный момент, я полностью согласен с JaredPars ответом.)

И «нет» в том, что когда RCW регенерируется (финализации называется), он будет автоматически «освобождение» COM-ссылка (фактически наберите FinalReleaseComObject). Помните, что, поскольку есть только один объект RCW, это означает, что он будет никогда не будет, если будет ссылка на него в .NET.Если RCW будет исправлен, то не проблема, потому что сверху нет ссылок на упомянутый RCW, и, следовательно, .NET знает, что он может уменьшить счетчик COM-адресов на один (что может привести к уничтожению COM-объекта) ,

Однако, так как .NET GC является finicky и недетерминированным, полагаясь на это поведение, это означает, что время жизни объекта не контролируется. Это может привести к тому, что много проблем при работе с объектной моделью Outlook. (Он может быть менее подвержен проблемам с другими COM-серверами, но OOM делает смешное «кэширование» объектов внутри страны. Легко получить исключение «Предмет уже изменен», если явно не контролировать время жизни.)

В моем коде у меня есть класс ComWrapper, который поддерживает IDisposable. Это позволяет мне передавать объекты RCW, полученные из COM-> NET, с ясным пожизненным правом собственности. У меня было очень мало проблем (почти ничего, фактически) в моей разработке Outlook-Addin после перехода на этот подход и множество вопросов, стоящих перед вами. «Недостатком» является то, что граница COM-> NET должна быть определена, но как только это произойдет, тогда внутренне все сроки жизни будут правильно обработаны.

Счастливое кодирование.

Смежные вопросы