2009-02-04 20 views
5

注:如何将接口指针传递给线程?

  • 使用原始的Win32 CreateTheard()API
  • 没有MFC
  • 接口仅仅是一个指向虚函数表

问:

  • 如何将接口指针传递给线程?

插图:

IS8Simulation *pis8 = NULL; 

... 

CoCreateInstance(
       clsid, 
       NULL, 
       CLSCTX_LOCAL_SERVER, 
       __uuidof(IS8Simulation), 
       (void **) &pis8); 



... 

hThread = CreateThread(
       NULL, 
       0, 
       SecondaryThread, 
       //interface pointer pis8 
       0, 
       &dwGenericThreadID); 

... 

DWORD WINAPI SecondaryThread(LPVOID iValue) 
{ 
    //using iValue accordingly 
    //E.g.: iValue->Open 

问候

回答

8

正如下面所述,在线程之间传递一个COM接口指针中并不安全。

假设你知道你在做什么:

hThread = CreateThread(
       NULL, 
         0, 
         SecondaryThread, 
         (LPVOID) pis8 
         0, 
         &dwGenericThreadID); 

DWORD WINAPI SecondaryThread(LPVOID iValue) 
{ 
    ((IS8Simulation*) iValue)->Open(); 
} 

线程安全的版本:

void MainThread() 
{ 
    IStream* psis8; 
    HRESULT res = CoMarshalInterThreadInterfaceInStream (IID_IS8SIMULATION, pis8, &psis8); 
    if (FAILED(res)) 
     return; 
    hThread = CreateThread(
       NULL, 
       0, 
       SecondaryThread, 
       (LPVOID) psis8 
       0, 
       &dwGenericThreadID 
     ); 
} 

DWORD WINAPI SecondaryThread(LPVOID iValue) 
{ 
    IS8Simulation* pis8; 
    HRESULT res = CoGetInterfaceAndReleaseStream((IStream*) iValue, IID_IS8SIMULATION, &pis8); 
    if (FAILED(res)) 
     return (DWORD) res; 
    pis8->Open(); 
} 
+0

@Quassnoi : 谢谢! – Aaron 2009-02-04 10:32:01

+0

这需要接口编组。 – Vinay 2009-02-04 15:13:58

6

如果你的问题的界面是一个COM接口,通过Quassnoi给出的方法可能是不够的。您必须注意正在使用的COM对象的线程模型。如果辅助线程将加入与创建COM对象的单独COM单元,并且该对象不是apartment-agile,则需要封送该接口指针,以便辅助线程获取代理,而不是直接指向对象的指针。

COM对象通常通过使用IMarshal的特殊实现进行公寓敏捷。最简单的方法是聚合Free Threaded Marshaler。

一些有用的链接...

更新:关于自由线程编组...

这是一个从意见明确关于这个话题,有些人会推荐这个话题你从不碰FTM。虽然“Effective COM”是一本很好的书,但我认为它的一些建议是可以解释的。第33项提到“小心FTM”;它不会说“永远不要使用FTM”。非常明智的是,它建议特别注意当你的公寓敏捷对象持有对其他对象的引用时,因为它们可能不是公寓敏捷的。所以真正的建议是:在构建公寓敏捷对象时仔细考虑,不管他们是否使用FTM来实现敏捷性。如果你确信你可以构建一个公寓敏捷的对象,我没有理由不使用FTM来实现它。

+0

FTM有危险的方面(参见Effective COM,第33项,“小心自由螺纹封送器”) – 2009-02-04 14:14:37

2

你基本上需要做到以下几点:

  • CoMashalInterThreadInterfaceInStream ==>你会得到一个IStream接口。
  • 将IStream传递给线程,例如正如Quassnoi所说。
  • 在SecondaryThread中,调用CoGetInterfaceAndReleaseStream来获取接口(或者如果需要的话,它的代理)。

除非创建线程失败,否则不要释放IStream接口,并且在yu调用CoGetInterfaceAndReleaseStream之前不要退出线程。

COM运行时将自动为您创建代理。该代理确保例如一个公寓线程的COM组件在创建它的线程上被调用。然而,这还要求:

  • 的接口是IDispatch接口,或代理/存根组件注册
  • 的threadthat创建的组件的界面具有一个消息循环和处理消息