Подскажите, есть ли какой-нибудь способ убить COM-объект, невзирая на его счетчик ссылок. Т.е. имеется ссылка на один из его интерфейсов и по ней надо его грохнуть?
Здравствуйте AlexeyV, Вы писали:
AV>Подскажите, есть ли какой-нибудь способ убить COM-объект, невзирая на его счетчик ссылок. Т.е. имеется ссылка на один из его интерфейсов и по ней надо его грохнуть?
Вызывать Release в цикле пока retval != 0. Но это может и не сработать...
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте TK, Вы писали:
AV>>Подскажите, есть ли какой-нибудь способ убить COM-объект, невзирая на его счетчик ссылок. Т.е. имеется ссылка на один из его интерфейсов и по ней надо его грохнуть?
TK>Вызывать Release в цикле пока retval != 0. Но это может и не сработать...
Я бы не стал на это полагаться по двум причинам. Во-первых, не смотря на то IUnknown::Release() возвращает ULONG, в спецификации COM не оговорено что это будет именно количество ссылок. Во-вторых, возможно, что компонент использует специфический механизм подсчёта ссылок, который не позволяет конкретному клиенту освободить больше, чем он взял (например, в COM+ это включается через консоль управления).
Прежде всего замечу, что такое поведение противоречит концепции архитектуры COM-приложений, и, если возможно, нужно постараться избежать необходимости в такой функциональности.
Приведу первый пришедший в голову способ. Создаётся интерфейс, скажем, IEmergencyLifetimeControl, имеющий метод DestroyObject(), который просто уничтожает объект на сервере. Затем в кокласс добавляется поддержка этого интерфейса и его реализация (которая, скажем, делает "delete this;").
Плох этот метод, помимо всего прочего тем, что необходимо иметь доступ к исходному коду кокласса, однако можно создать оболочку вокруг любого данного кокласса, которая будет реализовывать те же интерфейсы что и он путём переадресации вызовов, а так же иметь уже описанную функциональность. В этом случае можно избежать ряда проблем вроде "осиротевших" прокси путём предоставления некоторой функциональности даже если сам "пациент" уже покинул нас.
Да, кстати, в случае с COM+ можно предложить вариант с принудительно остановкой некоторого приложения.
Здравствуйте AlexeyV, Вы писали:
AV>Подскажите, есть ли какой-нибудь способ убить COM-объект, невзирая на его счетчик ссылок. Т.е. имеется ссылка на один из его интерфейсов и по ней надо его грохнуть?
я не пробовал, но как вариант можно вызывать Release(), не убивая ссылки, пока функция не вернет 0. Release возвращает количество оставшихся ссылок на объект.
Здравствуйте Shl, Вы писали:
Shl>[...] Release возвращает количество оставшихся ссылок на объект.
Release НЕ возвращает количество оставшихся ссылок на объект. Но он возвращает 0, если ссылок не осталось. Так что while(pObj->Release()); должно прокатить. Но это надругательство над COM, не делай так, и мир станет лучше (по крайней мере не станет хуже (по крайней мере станет хуже не из-за этого)).
Здравствуйте AlexeyV, Вы писали:
AV>Подскажите, есть ли какой-нибудь способ убить COM-объект, невзирая на его счетчик ссылок. Т.е. имеется ссылка на один из его интерфейсов и по ней надо его грохнуть?
Посмотрите в MSDN функцию
CoDisconnectObject()
CoLockObjectExternal()
может поможет
Первая позволяет отконнектиться от внешних клиентов.
У второй обратите внимание на последний параметр.