Я не могу не публиковать это, хотя это не прямой ответ на вопрос.
Есть блестящая статья MSKB из золотых веков Com: Информация: описания и работы моделей OLE потоков. Анкет Все еще там, и имеет всю соответствующую информацию. Дело в том, что вы не должны беспокоиться о том, есть ли маршалинг или нет, если вы следуете правилам. Анкет Просто зарегистрируйте свой объект как ThreadingModel=Both
, объединить маршалер свободного нагрузки CoCreateFreeThreadedMarshaler
, и быть сделанным. COM сделает маршалинг, если это необходимо, наилучшим образом. В зависимости от модели квартиры клиента, клиент -код может получить прямой указатель на ваш интерфейс, если он также следует за правилами.
Любой «инопланетный» интерфейс, который вы можете получить, когда будет вызван метод вашего интерфейса, будет действительным в области вызова, поскольку вы остаетесь в одном и том же потоке. Если вам не нужно хранить его, это все, что имеет значение.
Однако, если вам нужно кэшировать интерфейс «инопланетянина», правильным способом сделать это будет хранение его с помощью CoMarshalInterThreadInterfaceInStream
/CoGetInterfaceAndReleaseStream
:
Чтобы хранить это:
- Введите критический раздел;
- вызов
CoMarshalInterThreadInterfaceInStream
и хранить IStream
указатель в поле участника;
- Оставить критический раздел;
Чтобы получить это
- Введите критический раздел;
- вызов
CoGetInterfaceAndReleaseStream
Чтобы получить интерфейс
- вызов
CoMarshalInterThreadInterfaceInStream
и хранить его снова как IStream
Для любого будущего использования
- Оставить критический раздел;
- Используйте интерфейс в области текущего вызова
Чтобы освободить:
- Когда вам больше не нужно сохранять его, просто отпустите сохранение
IStream
(Внутри критического раздела).
Если объект «инопланетянина» тоже свободно нагружен, а вещи происходят в том же процессе, вы, вероятно, будете иметь дело с прямым указателем интерфейса после CoGetInterfaceAndReleaseStream
. Анкет Тем не менее, вы не должны делать никаких предположений, и вам действительно не нужно знать, является ли объект, с которым вы работаете, является оригинальным объектом или прокси -сервером Com Marshaller.
Это может быть слегка оптимизировано с помощью CoMarshalInterface
w/ MSHLFLAGS_TABLESTRONG
/ CoUnmarshalInterface
/ IStream::Seek(0, 0)
/ CoReleaseMarshalData
вместо CoGetInterfaceAndReleaseStream
/CoGetInterfaceAndReleaseStream
, чтобы не считать тот же интерфейс столько раз, сколько необходимо, не выпустив поток.
Возможны более сложные (и, возможно, более эффективные) сценарии кэширования, включающие ниточное локальное хранение. Тем не менее, я считаю, что это будет излишним. Я не делал времени, но я думаю, что накладные расходы CoMarshalInterThreadInterfaceInStream
/CoGetInterfaceAndReleaseStream
действительно низкий.
Тем не менее, если вам нужно поддерживать состояние, которое хранит любые ресурсы или объекты, которые могут потребовать сродства потока, кроме вышеупомянутых интерфейсов COM, вы не должна Отметьте свой объект как ThreadingModel=Both
или объединить FTM.