Я не могу помочь себе отправляю это, хотя он не является прямым ответом на вопрос.
Существует блестящая статья MSKB от золотых веков COM: INFO: Descriptions and Workings of OLE Threading Models. Все еще есть и имеет всю необходимую информацию. Дело в том, что вы не должны беспокоиться о том, есть ли маршалинг или нет, если вы следуете правилам. Просто зарегистрируйте свой объект как ThreadingModel=Both
, соберите Free-Threaded Marshaler с CoCreateFreeThreadedMarshaler
и сделайте это. COM будет делать маршалинг, если необходимо, наилучшим образом. В зависимости от модели квартиры клиента код клиента может получать прямой указатель на ваш интерфейс, если он также следует правилам.
Любой интерфейс «чужой», который вы можете получить при вызове метода вашего интерфейса, будет действительным в области вызова, потому что вы остаетесь в одном потоке. Если вам не нужно его хранить, это все, что имеет значение.
Если же вам нужно кэшировать «чужеродные» интерфейс, правильный способ сделать это было бы хранить его с помощью CoMarshalInterThreadInterfaceInStream
/CoGetInterfaceAndReleaseStream
:
Чтобы сохранить его:
- Введите критический раздел;
- позвонить
CoMarshalInterThreadInterfaceInStream
и сохранить указатель IStream
в поле участника;
- Оставить критический участок;
Чтобы получить его
- Введите критическую секцию;
- вызов
CoGetInterfaceAndReleaseStream
получить интерфейс
- вызова
CoMarshalInterThreadInterfaceInStream
и хранить его снова, как IStream
для любого будущего использования
- Оставьте критическую секцию;
- Используйте интерфейс в рамках текущего вызова
Чтобы освободить его:
- Когда вам больше не нужно не держать его, просто отпустите хранимая
IStream
(в критической секции).
Если «чужой» объект свободен нарезка тоже, и все происходит в том же процессе, вы, вероятно, будете иметь дело с прямым указателем интерфейса после CoGetInterfaceAndReleaseStream
. Однако вы не должны делать каких-либо предположений, и вам действительно не нужно знать, является ли объект, с которым вы работаете, оригинальным объектом или прокси-сервером COM-маршаллера.
Это может быть слегка оптимизированы с помощью CoMarshalInterface
ж/MSHLFLAGS_TABLESTRONG
/CoUnmarshalInterface
/IStream::Seek(0, 0)
/CoReleaseMarshalData
вместо CoGetInterfaceAndReleaseStream
/CoGetInterfaceAndReleaseStream
, чтобы распаковать и тот же интерфейс столько раз, сколько необходимо, не выпуская поток.
Возможны более сложные (и, возможно, более эффективные) сценарии кэширования с использованием локального хранилища потоков. Однако я считаю, что это будет излишним. Я не делал никаких сроков, но я думаю, что накладные расходы CoMarshalInterThreadInterfaceInStream
/CoGetInterfaceAndReleaseStream
действительно низкие.
Тем не менее, если вам необходимо поддерживать состояние, что хранит какие-либо ресурсы или объекты, которые могут потребовать резьбы сродства, кроме вышеупомянутых COM интерфейсов, вы не должны знака своего объекта как ThreadingModel=Both
или агрегирования FTM.
Ах. Возможный дубликат: http://stackoverflow.com/questions/3460071/does-it-require-to-marshal-the-com-object-supporting-threading-model-both?rq=1 –