Освободить компоненты COM - PullRequest
5 голосов
/ 03 октября 2008

Действительно ли необходимо выпускать компоненты COM из Office PIA, когда они вам больше не нужны, вызывая Marshal.ReleaseComObject (..)?

Я нашел в Интернете различные и противоречивые советы по этой теме. По моему мнению, поскольку Outlook PIA всегда возвращает новые ссылки на свои интерфейсы как возвращающие значения из своих методов, нет необходимости явно освобождать его. Я прав?

Ответы [ 8 ]

2 голосов
/ 04 августа 2010
2 голосов
/ 03 октября 2008

В общем случае с Microsoft Office вам необходимо явно опубликовать свои ссылки, что можно безопасно сделать в два этапа:

(1) Сначала освободите все второстепенные объекты, для которых вы не держите именованную переменную объекта, с помощью вызова GC.Collect (), а затем GC.WaitForPendingFinalizers (). (Вам необходимо вызывать это дважды, если задействованные объекты могут иметь финализаторы, например, при использовании Visual Studio Tools for Office (VSTO).)

(2) Затем явно освободите объекты, для которых вы держите именованную переменную, с помощью вызова Marshall.FinalReleaseComObject () для каждого объекта.

Вот и все. : -)

Я обсуждал это более подробно в предыдущем посте вместе с примером кода.

2 голосов
/ 03 октября 2008

PIA - это оболочки взаимодействия .NET. Это означает, что в деструкторе объекта (или Dispose - я не помню) будет автоматически обрабатывать его счетчик ссылок. Хитрость в том, что некоторые ссылки не будут освобождены, пока не будет выполнен сборщик мусора. Это зависит от того, что создает объект COM. Например, COM-объект, открывающий курсоры базы данных, будет поддерживать эти курсоры в памяти до тех пор, пока счетчик ссылок на эти курсоры не будет освобожден. При взаимодействии .NET / COM ссылки не освобождаются до тех пор, пока не выполнится сборщик мусора или вы не освободите ссылку явно с помощью Marshal.ReleaseComObject (или FinalReleaseComObject).

Лично я не работал с PIA Microsoft Office, но в большинстве случаев вам не нужно иметь для явного освобождения ссылок. Только когда ваше приложение начинает блокировать другие ресурсы или происходит сбой, вы должны начать подозревать висячие ссылки.

РЕДАКТИРОВАТЬ: Если вы столкнетесь с ситуацией, когда вам нужно очистить объекты COM / Interop, используйте Marshal.FinalReleaseComObject - который берет счетчик ссылок до нуля, а не просто уменьшает его на единицу и установите ссылку на объект на ноль. Вы можете явно форсировать сборку мусора (GC.Collect), если вы действительно хотите быть в безопасности, но будьте осторожны с выполнением GC слишком часто, так как это вызывает заметное снижение производительности.

1 голос
/ 03 октября 2008

Существует несколько хороших практик здесь с использованием управляемой оболочки ... стоит проверить ..

0 голосов
/ 04 октября 2008

Существует одно простое правило о взаимодействии .Net / COM - если есть сомнения, всегда Release () : -)

0 голосов
/ 03 октября 2008

Мой опыт показывает, что это необходимо, иначе (по крайней мере, Outlook) приложение может вообще не закрыться.

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

Я разместил соответствующий вопрос здесь , но у меня все еще нет четкого ответа. Я буду редактировать этот пост, как только узнаю больше.

0 голосов
/ 03 октября 2008

Это необходимо сделать, если вы хотите, чтобы экземпляр приложения Office завершился, как описано в этом сообщении .

И трудно понять это правильно во всех, кроме самых простых сценариев.

0 голосов
/ 03 октября 2008

Возможно, это просто мое суеверие, но я решил явно выпустить Office PIA через Marshal.ReleaseComObject (), потому что, когда мое приложение зависало, ссылки на Excel и Word оставались открытыми. Я не слишком углублялся в причину (глупые сроки), но выпуская их как часть шаблона распоряжения моего класса, решил эту проблему.

...