我不禁要发布此内容,尽管这不是对问题的直接答案。
com的黄金时代有一篇精彩的MSKB文章: 信息:OLE线程模型的描述和工作. 。仍然在那里,并拥有所有相关信息。 关键是,如果您遵守规则,您不必担心是否有编组. 。只需将您的对象注册为 ThreadingModel=Both
, ,将自由线的元帅与 CoCreateFreeThreadedMarshaler
, ,完成。如果需要,COM将以最好的方式进行安排。根据客户端的公寓模型,如果遵循规则,客户端代码也可以接收到界面的直接指针。
当调用接口的方法时,您可能会收到的任何“外星人”接口在呼叫的范围中都是有效的,因为您保持在同一线程上。 如果您不需要存储它,那很重要。
但是,如果您确实需要缓存“外星人”界面,那么正确的方法就是使用它来存储它 CoMarshalInterThreadInterfaceInStream
/CoGetInterfaceAndReleaseStream
:
存储它:
- 输入关键部分;
- 称呼
CoMarshalInterThreadInterfaceInStream
并存储 IStream
成员领域的指针;
- 留下关键部分;
检索它
- 输入关键部分;
- 称呼
CoGetInterfaceAndReleaseStream
检索界面
- 称呼
CoMarshalInterThreadInterfaceInStream
并再次将其存储为 IStream
用于以后的任何用途
- 留下关键部分;
- 使用当前呼叫范围中的接口
发布它:
- 当您不再需要保留它时,只需释放存储的
IStream
(在关键部分内)。
如果“外星人”对象也是免费的,并且事物在同一过程中发生,那么您可能会处理直接接口指针。 CoGetInterfaceAndReleaseStream
. 。但是,您不应该做出任何假设,也不需要知道处理的对象是原始对象还是com邮政使用者代理。
通过使用可以稍微优化这 CoMarshalInterface
w/ MSHLFLAGS_TABLESTRONG
/ CoUnmarshalInterface
/ IStream::Seek(0, 0)
/ CoReleaseMarshalData
代替 CoGetInterfaceAndReleaseStream
/CoGetInterfaceAndReleaseStream
, ,要根据需要多次汇总相同的接口,而无需释放流。
更复杂(可能更有效)的缓存方案是可能的,涉及线程本地存储。但是,我相信那将是过度杀伤。我没有做任何时机,但我认为 CoMarshalInterThreadInterfaceInStream
/CoGetInterfaceAndReleaseStream
真的很低。
也就是说,如果您需要保持一个状态 存储任何可能需要线程亲和力的资源或对象, ,除了上述com接口外,您 不应该 将您的对象标记为 ThreadingModel=Both
或汇总FTM。