Соответствует ли ReleaseComObject аннулированию подписки на обработчик событий? - PullRequest
0 голосов
/ 17 января 2012

В моем классе определен новый член COMObject

protected COMObject.Call call_ = null;

В этом классе есть следующий обработчик событий, на который я подписан

call_.Destructed += new COMObject.DestructedEventHandler(CallDestructedEvent);

использует

Marshal.ReleaseComObject(call_) 

равно

call_.Destructed -= new COMObject.DestructedEventHandler(CallDestructedEvent);

1 Ответ

2 голосов
/ 17 января 2012

Совсем нет.Когда вы создаете COM-объект, он создается с количеством ссылок 1 на его RCW.Когда вы подписываетесь на событие, счетчик ссылок увеличивается, поскольку объект также получает ссылку через свой контейнер точки подключения с помощью CCW, еще одной оболочки для вызовов, исходящих из объекта, обратно в ваш обработчик событий.

Marshal.ReleaseComObject() уменьшает счетчик на RCW на единицу, таким образом, вы не заявляете о намерении больше вызывать объект.Но объект все еще может вызывать ваш обработчик событий.Это верно, даже если вы вызываете Marshal.ReleaseComObject() несколько раз (до тех пор, пока он не возвращает 0), или вызываете Marshal.FinalReleaseComObject(), который по существу освобождает объект, пока счетчик ссылок на RCW не уменьшится до 0. RCWосвобождается, и вы больше не можете вызывать объект, но CCW все еще рядом, так что он все еще может инициировать события.

Теперь, даже если вам удалось освободить объект, это было бы небезопасно в любом случае: что если вызов обработчика событий уже выполняется?Это приведет к освобождению объекта с его кодом в активном стеке.Поведение в этом случае не определено.

Таким образом, безопасный способ освобождения COM-объекта состоит в том, чтобы одновременно аккуратно отписаться от всех подписанных событий, а затем вызвать Marshal.FinalReleaseComObject() для освобождения RCW, и, таким образом, сделать этосам объект.Даже если вы сделаете это из обработчика событий, COM-объект не умрет немедленно, так как он предположительно содержит дополнительную ссылку на себя во время вызова, если он написан правильно.

Смотрите также: Оболочки, вызываемые во время выполнения COM-Callable Wrappers IConnectionPointContainer в неуправляемом мире.

...