在过去的几天里,我一直在努力为一个应用程序找到一个好的架构,经过一番研究后,我终于陷入困境,原因就是 COM。
相关应用程序将有多个 GUI 线程,它们将为工作线程安排工作项。工作线程将通过 CoInitialize(NULL); 初始化 COM,创建一些 COM 组件,然后进入一个等待 WaitForMultipleObjects(2, ...) 的循环(ExitEvent - 指示应用程序正在关闭,ManualResetEvent - 指示实际上有工作项需要处理),并且在成功等待后,将处理这些项并将它们发送回 GUI 线程。如果队列为空,ManualResetEvent 将在工作线程内部重置,并将发生在队列关键部分内。
问题是,像往常一样,COM 让一切都变得困难 1000 倍……
如果我理解正确的话,CoInitialize(NULL);创建一个隐藏窗口,在 WaitForSingle/MultipleObject/s 期间发布的任何消息都可能导致死锁。
因此,我需要调用 MsgWaitForMultiple 对象。如果消息没有正确泵送,这反过来可能会失败。不幸的是,我不太明白如何以正确的方式泵送它们。我必须创建自己的消息循环吗?如果 COM 决定创建消息框,应用程序会崩溃吗?
到目前为止,我似乎必须这样进行?
HANDLE hEvents[2] = {};
int ThreadProc(LPVOID lpParam) {
int nRetVal = 0;
CoInitialize(NULL);
CComPtr<ISomething> smthn;
smthn.CoCreateInstance(...);
MSG msg = {};
bool bRun = true;
while(bRun) {
while(PeekMessage(&msg, ??NULL/-1??, 0, 0, PM_REMOVE)) { /*Which one here?*/
if(msg.Message == WM_QUIT) {
bRun = false;
nRetVal = msg.wParam;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(MsgWaitForMultipleObjects(2, &hEvents, ...)) {
if(exitevent) { bRun = false; nRetVal = 0; }
else if(processevent) { [processdata] }
}
}
smthn.release();
CoUninitialize();
return nRetVal;
}
但是隐藏窗口、消息框呢?我是否走在正确的道路上?