Предположим, у меня есть COM-объект (неуправляемый) и .NET Client.Интеграция .NET и COM: выпуск COM из .NET-клиента
Нужно ли позвонить из .NET-клиента Marshal.FinalReleaseComObject
, чтобы освободить COM-объект?
Предположим, у меня есть COM-объект (неуправляемый) и .NET Client.Интеграция .NET и COM: выпуск COM из .NET-клиента
Нужно ли позвонить из .NET-клиента Marshal.FinalReleaseComObject
, чтобы освободить COM-объект?
Нет. Нет необходимости явно освобождать объект COM от клиента .Net. COM-объект будет собран, как и любой другой .Net-объект, и будет выпущен его основной дескриптор, когда все ссылки на него будут удалены.
Явное использование FinalReleaseComObject
может фактически привести к ошибкам программирования. Если другой компонент вашего кода все еще ссылается на объект COM, вы будете вытаскивать из него собственный объект. Это, возможно, приведет к сбоям во время работы в будущем.
Хотя «теоретически» может быть нет потребность, «на практике», там * определенно есть *. Кроме того, не используйте FinalReleaseComObject, а скорее ReleaseComObject для * каждый раз, когда любой COM-объект был перенесен на границу COM.NET. Я программирую Outlook Addin: я могу сказать, что предоставление объектов * явное время жизни - единственный способ создать рабочую надстройку *. Период. (Я использую класс helper/wrapper, который поддерживает Dispose, я использую 'use'.) –
Неправильная практика. Вы GC.Collect() + GC.WaitForPendingFinalizers(), если вам нужно, никогда не ошибаетесь. –
@HansPassant Это не работает с объектной моделью Outlook. Различные связанные «решения» включают попытку вызывать эту последовательность * дважды * подряд. Он просто не работает «на практике» (в тех случаях, когда я занимаюсь). –
A изменен «Да» и «Нет».
Прежде всего, имейте в виду, что ReleaseComObject
не автоматически уменьшает реальный COM-объект ref-count. Скорее он уменьшает внутренний счетчик RCW. (Каждый раз, когда тот же объект COM перемещается из COM-> NET, он будет использовать тот же RCW и увеличивать счетчик RCW на единицу.) Аналогично, FinalRelaseComObject
также влияет на счетчик RCW, эффективно «устанавливает его на 0». Это когда счетчик RCW обращается в ноль, что .NET будет уменьшать значение COM ref-count.
Так, "да", но модифицирована для этих правил:
ReleaseComObject
, но неFinalReleaseComObject
, ссылается на него. То есть, он должен быть вызван один раз за каждый раз, когда объект пересекает, , даже если он приводит к эталонному значению RCW.Я говорю правила выше и не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 должна быть определена, но как только это произойдет, тогда внутренне все сроки жизни будут правильно обработаны.
Счастливое кодирование.
http://blogs.msdn.com/b/visualstudio/archive/2010/03/01/marshal-releasecomobject-considered-dangerous.aspx –
Спасибо - очень полезная статья –