【发布时间】:2011-04-18 21:37:39
【问题描述】:
过去我在多线程方面做了很多工作,但我对 COM 还很陌生。无论如何,这是我的问题:
我创建了一个工作线程,它注册为一个 STA,并创建了一个 COM 对象。然后工作线程和主线程尝试相互通信。使用CoMarshalInterThreadInterfaceInStream 和CoGetInterfaceAndReleaseStream,我可以让线程调用另一个线程中COM 对象的方法。
工作线程如下所示:
void workerThread()
{
CoInitialize(NULL);
MyLib::IFooPtr foo = ...; // create my COM object
// Marshall it so the main thread can talk to it
HRESULT hr = CoMarshalInterThreadInterfaceInStream(foo.GetIID(),
foo.GetInterfacePtr(),
&m_stream);
if (FAILED(hr)) {
// handle failure
}
// begin message loop, to keep this STA alive
MSG msg;
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1) break;
DispatchMessage(&msg);
}
}
在主线程中:
// launch the thread
m_worker = boost::thread (&workerThread);
// get the interface proxy
MyLib::IFooPtr foo;
LPVOID vp (NULL);
HRESULT hr = CoGetInterfaceAndReleaseStream(m_stream, foo.GetIID(), &vp);
if (SUCCEEDED(hr)) foo.Attach(static_cast<MyLib::IFoo*>(vp));
这会创建对象(这需要一段时间来初始化),并允许主线程与之对话,并且一切都与 COM Apartment 的东西正确同步。据我从阅读 msdn 可以看出,这似乎是做事的正确方法。现在主线程可以使用它的代理来调用我的 COM 对象上的方法,并且工作线程将通过消息队列接收这些调用,并正确地分派它们。
但是,如何同步这些线程?
显然在这种情况下,我希望主线程等待调用CoGetInterfaceAndReleaseStream,直到工作线程通过CoMarshalInterThreadInterfaceInStream 创建该流之后。但我怎样才能安全地做到这一点呢?
从MSDN 开始,我应该使用MsgWaitForMultipleObjects 之类的东西,所以我可以等待 my_condition 或 new_message_arrived,然后我可以执行以下操作:
// verbatim from msdn
while (TRUE)
{
// wait for the event and for messages
DWORD dwReturn = ::MsgWaitForMultipleObjects(1,
&m_hDoneLoading, FALSE, INFINITE, QS_ALLINPUT);
// this thread has been reawakened. Determine why
// and handle appropriately.
if (dwReturn == WAIT_OBJECT_0)
// our event happened.
break ;
else if (dwReturn == WAIT_OBJECT_0 + 1)
{
// handle windows messages to maintain
// client liveness
MSG msg ;
while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
::DispatchMessage(&msg) ;
}
}
但是如何将boost::thread.join() 和boost::condition.wait() 与MsgWaitForMultipleObjects 混合使用?这甚至可能吗,还是我必须做其他事情来避免竞争条件?
【问题讨论】:
标签: c++ multithreading com boost synchronization