将 COM 接口编组到多个线程时,克隆流是不是足够,还是需要复制?
Posted
技术标签:
【中文标题】将 COM 接口编组到多个线程时,克隆流是不是足够,还是需要复制?【英文标题】:When marshaling a COM interface to multiple threads, is cloning the stream sufficient, or is copying it necessary?将 COM 接口编组到多个线程时,克隆流是否足够,还是需要复制? 【发布时间】:2021-10-28 17:52:18 【问题描述】:根据Raymond's guide,在将 COM 接口编组到多个线程时,您必须“[t]将流的副本传输到要与之共享对象的每个线程。 " (或者您可以使用互斥体,但我们暂时先搁置该选项。)
我想知道使用IStream::Clone
是否足以达到此目的,或者这是否不算作副本。
另外,如果IStream::Clone
很好,我想知道您是否需要从创建原始流的线程中调用它,或者是否有一个后台线程可以调用它。我想知道,如果后台线程调用它,您是否会遇到我们一开始就试图避免的确切情况(跨线程共享 COM 指针)。
感谢您提供任何信息。
【问题讨论】:
不是从 Windows 8.1 开始,您只需要 RoGetAgileReference(在同一进程中)。 @SimonMourier 是的,我在 Windows 8.1 上尝试了RoGetAgileReference
,但收到了E_NOTIMPL
。
@SimonMourier RoGetAgileReference()
可用于编组指向线程的接口指针。但它不会为该接口制作单独的副本以供多个线程使用。
什么意义将对象传递给多个线程?所以真的要多次通过同一个任务来池?几乎 100% 这是设计错误
@RbMm 那么为什么 Raymond 会提供如何操作的说明呢?为什么MSHLFLAGS_TABLESTRONG
存在?
【参考方案1】:
是的,如果不使用同步互斥锁,您需要 Clone()
每个线程的原始流,这样每个克隆都有自己独立于其他克隆的读/写查找位置。
Clone 方法使用自己的查找指针创建一个新的流对象,该指针引用与原始流相同的字节。
Raymond 的指南甚至避开了这一点:
将流的副本传输到要与之共享对象的每个线程。 (你需要使用一个副本,这样多个线程就不会都尝试使用同一个流并踩到彼此的流位置。或者,你可以聪明地使用同一个流,但是使用互斥锁或其他同步对象来确保一次只有一个线程使用流。)
【讨论】:
谢谢。您是否需要从创建原始流的线程中调用IStream::Clone
,或者后台线程之一可以调用它?我想知道是否有后台线程调用它,那么您最终会遇到我们一开始就试图避免的确切情况——跨线程共享 COM 指针。
@user15284017 原始线程创建克隆并将它们传递给每个线程会更安全。否则,如果线程尝试创建自己的克隆,则确实存在竞争条件。以上是关于将 COM 接口编组到多个线程时,克隆流是不是足够,还是需要复制?的主要内容,如果未能解决你的问题,请参考以下文章
该应用程序调用了一个为不同线程编组的接口 - Xamarin Forms
应用程序调用了为不同线程编组的接口 - Windows Store App