Руководство по подсчету ссылок на взаимодействие COM - PullRequest
5 голосов
/ 05 марта 2010

Недавно я потратил довольно много времени на написание различных проектов Visual Studio Extensions. Несмотря на то, что все проекты представляют собой управляемый код для доступа к основным службам VS, все равно необходимо работать с интерфейсами COM старого стиля.

Вот пример:

var selectionTracker = (IVsMonitorSelection)serviceProvider.GetService(typeof(SVsShellMonitorSelection));
IntPtr ppHier;
uint pitemid;
IVsMultiItemSelect ppMIS;
IntPtr ppSC;
selectionTracker.GetCurrentSelection(out ppHier, out pitemid, out ppMIS, out ppSC)))

как вы можете видеть, этот вызов возвращает 2 указателя (ppHier и ppSC) и объект ppMIS. Вопрос в том, как лучше играть с подсчетом ссылок COM.

Насколько я понимаю, в мире COM, когда метод возвращает указатель на объект, этот указатель является AddRef'ed до его возвращения. Это означает, что для предотвращения утечки COM-объектов я должен освободить их, когда я их использую.

Я также предполагаю, что то, что я получаю как объект, уже заключено в RCW, который позаботится об освобождении ссылки, когда она будет завершена.

Эти два предположения, примененные к вышеуказанному вызову, означают, что я должен обязательно вызвать `Marshal.Release 'на моих 2 указателях, но я не должен ничего делать с подсчетом ссылок в отношении возвращаемого объекта.

Перефразируя мой вопрос: если предположить, что используемые COM-объекты воспроизводятся по правилам COM, является ли подход, описанный выше, правильным способом для подсчета ссылок COM?

1 Ответ

0 голосов
/ 06 марта 2010

В этом конкретном сценарии вам нужно будет вызвать Marshal.Release для переменных IntPtr , иначе они не исчезнут.Конечно, если вы скажете маршаллеру просто использовать объект (или определенный тип) напрямую, вам не придется беспокоиться об этом, так как RCW обеспечит уничтожение объекта в какой-то момент в будущем (то есть, когда вызывается финализатор впроцесс сбора мусора).

Конечно, подход финализатора может происходить в недетерминированный момент времени, поэтому, если объект поддерживает некоторый ресурс, от которого вам нужно избавиться, в идеале следует вызвать Marshal.ReleaseComObject для уменьшенияего счетчик ссылок до того, как упаковщик сделает для вас выпуск.

...