VC ++线程编组和COM:应用程序调用了为另一个线程编组的接口

osu*_*sum 3 com multithreading visual-c++

我的基于VC ++ 2005对话框的应用程序初始化对话框类中的COM对象,并在工作线程中使用它。

我在应用程序的开头和工作线程的开头调用了CoInitialize(NULL)。但是,当调用COM方法时,将出现错误“该应用程序调用了已编组为不同线程的接口”。

如果我使用CoInitializeEx(0,COINIT_MULTITHREADED),则会收到相同的错误消息

请帮助我找到根本原因。

谢谢。

Han*_*ant 5

您通过调用CoInitialize(NULL)创建了两个单线程单元。必须先将接口指针从一间公寓编组到另一间公寓,然后才能使用。将工作线程初始化为MTA不能解决问题。原始接口指针仍在单线程单元中创建,因此不是线程安全的。换句话说,您不能直接从线程调用接口方法。这些调用必须编组到创建接口的线程中。对接口指针进行封送处理可建立使之成为可能的管道。

唯一不需要封送的时间就是两个线程都是MTA时。这几乎是不可能的,如果创建任何窗口,您的主线程必须是STA。而且COM服务器实际上必须是线程安全的,而很少有。他们使用注册表中的ThreadingModel密钥发布所需的广告。如有必要,COM实际上将创建一个STA线程来为服务器找到一个良好的家。

您必须使用CoMarshalInterThreadInterfaceInStream()封送指针,以避免发生错误。那是一个相当不友好的功能,IGlobalInterfaceTable更易于使用。COM服务器也必须支持它,通常需要代理/存根DLL来处理封送处理。如果没有,您将得到E_NOINTERFACE。

同样要当心开销,将工作线程到主线程的调用进行封送处理非常昂贵,并且要视主线程的响应速度而定。换句话说,如果您编写线程来加快程序速度或避免阻塞用户界面,则此操作实际上将不起作用。这是“没有免费的午餐”的原则。