C++ 工作线程如何与主UI线程通信?
工作线程与主UI线程通信的最佳方式是什么 小结:我的C++/MFC应用程序是基于对话框的。要进行冗长的计算,主UI线程将创建几个辅助线程。工作线程在计算过程中进行时,会将其进度报告给主UI线程,然后主UI线程会显示进度 这适用于共享内存中的数字进度值(由工作人员编写,由UI读取),但我在处理文本进度消息时遇到了问题。我尝试的解决方案已经经过了多次迭代,但似乎都不起作用C++ 工作线程如何与主UI线程通信?,c++,multithreading,mfc,C++,Multithreading,Mfc,工作线程与主UI线程通信的最佳方式是什么 小结:我的C++/MFC应用程序是基于对话框的。要进行冗长的计算,主UI线程将创建几个辅助线程。工作线程在计算过程中进行时,会将其进度报告给主UI线程,然后主UI线程会显示进度 这适用于共享内存中的数字进度值(由工作人员编写,由UI读取),但我在处理文本进度消息时遇到了问题。我尝试的解决方案已经经过了多次迭代,但似乎都不起作用 我让UI线程将指向控件的指针传递给工人,工人直接更新UI。这不是很有效,而且似乎是错误的方法 我让工作人员使用SendMessa
UIMessage *pUI=new UIMessage; // so it won't go out of scope (main dialog will delete it)
pUI->buffer=traceLineBuffer; pUI->nOutputs=traceN;
BOOL ok=::PostMessage(hWndMainDlg,TraceLineMsg,(WPARAM)pUI, NULL/*lParam*/);
BEGIN_MESSAGE_MAP(CMainDlg, CDialog)
...
ON_MESSAGE(TraceLineMsg,OnTraceLineMsg)
...
END_MESSAGE_MAP()
LRESULT CMainDlg::OnTraceLineMsg(WPARAM wParam, LPARAM lParam)
{
UIMessage *pUI=(UIMessage *)wParam;
char *p=pUI->buffer;
// PROCESS BUFFER
delete[] pUI->buffer;
delete pUI;
return 0;
}
UI正在接收它们,代码如下
UIMessage *pUI=new UIMessage; // so it won't go out of scope (main dialog will delete it)
pUI->buffer=traceLineBuffer; pUI->nOutputs=traceN;
BOOL ok=::PostMessage(hWndMainDlg,TraceLineMsg,(WPARAM)pUI, NULL/*lParam*/);
BEGIN_MESSAGE_MAP(CMainDlg, CDialog)
...
ON_MESSAGE(TraceLineMsg,OnTraceLineMsg)
...
END_MESSAGE_MAP()
LRESULT CMainDlg::OnTraceLineMsg(WPARAM wParam, LPARAM lParam)
{
UIMessage *pUI=(UIMessage *)wParam;
char *p=pUI->buffer;
// PROCESS BUFFER
delete[] pUI->buffer;
delete pUI;
return 0;
}
问题:
64位Windows 7、Visual Studio 2010、本机C++/MFC,主线程位于WaitForMultipleObjects调用中,不会处理任何消息,也不会更新任何控件或其他窗口。解决方案是:不要这样做。在GUI上发布进度报告的速度要比用户能够理解的速度快,这没有多大意义。当其他线程中有大量活动时,通常会使用GUI计时器轮询线程中的进度变量,因此每500毫秒更新一次GUI控件 这是计时器轮询实际上具有优势的极少数情况之一。您可以获得peridoc进度报告,而不会在GUI Windows消息队列中塞满更新。例如,uTorrent客户端(存在大量网络活动的地方)使用此方案-尝试更新收到的每个网络协议单元上的GUI下载统计信息肯定会填满GUI
(5)中的缓冲方案应该是有效的。我经常通过将对象指针加载到LPARAM或WPARAM中,在工作线程中新建大型数据项,并在显示后在GUI中删除它们,从而将大型数据项传输到主GUI线程。您的(5)应该已经工作了,并且至少减少了进度数据传输的开销。我只能假设要显示的数据量仍然太大,因此GUI线程仍然无法跟上:(Windows上的MFC工作线程有多个与主线程通信的选项。您有标准的线程信号和同步(互斥、信号量等),使用方便,性能更高的机制
// syncronization
{
CSingleLock lock(&sharedCriticalSection,TRUE);
sharedList.push_back(msg);
}
// other thread(s) are blocked/pending or you send an event or message to signal
// messages
Data* data = new Data(payload);
PostMessage(hWnd, REGISTERED_MESSAGE, 0, (LPARAM)data);
// target window handles message and deletes data
// if it is not blocked or too slow and the queue overflows
// skipping lots of IO completion port boilerplate and showing the key methods
messagePort = CreateIoCompletionPort(...);
...
GetQueuedCompletionStatus(messagePort,...);
...
PostQueuedCompletionStatus(messagePort,...);
如果您阻塞或忙着等待线程完成,它们都不会完成很多工作,也不会提高您的性能或响应能力
对你的意见的评论:
发布消息是一种方法。但您是否考虑过大幅减少消息数量?为什么不每100或1000条消息更新一次?您所采取的方法是正确的,但发送足够的消息以超过队列限制确实没有意义。唯一可能导致未收到已发布消息的是溢出g队列限制或阻止主线程,如在睡眠或等待..调用中。在发布这些消息时,主线程在做什么?您是否也为每条消息分配了另一个traceLineBuffer?koodawg:我确实通过将消息缓冲在(5)中来减少消息的数量.ScottMcP MVP:在工作线程完成之前,主线程处于WaitForMultipleObjects中。可能这就是问题所在。是的,为每条消息分配了一条新消息和缓冲区,您可以从我在OnTraceLineMsg中删除它们中看到。我应该