工作线程与主 UI 线程之间通信的最佳方式是什么?
总结:我的 C++/MFC 应用程序基于对话框开发。为了进行冗长的计算,主 UI 线程创建了多个工作线程。随着工作线程在计算中的进展,它们向主 UI 线程报告其进度,然后主 UI 线程显示进度。
对于在共享内存中的数字进度值,这可以正常工作(由工作线程写入,由 UI 读取),但是我在文本进度消息方面遇到了麻烦。我的尝试解决方案已经经历了多次迭代,但似乎都不起作用。
我让 UI 线程向工作线程传递控件指针,然后工作线程直接更新 UI。这样并不是很有效,并且似乎是错误的方法。
我让工作线程通过 SendMessage 向 UI 线程的窗口发送消息。这会导致死锁。(SendMessage 直到消息被处理才会返回。)
与第2种相同,只是使用 PostMessage 向 UI 线程的窗口发送消息。这在一段时间内有效,但是消息丢失了。(PostMessage 立即返回。)进一步调查发现,消息队列的配额(默认为10,000)已超过。
我增加了消息队列的配额(在注册表中变量 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\USERPostMessageLimit),但丢失的消息数量没有改变。
我让每个工作线程将消息缓存在4 KByte 的缓冲区中,并在缓冲区填满时使用 PostMessage。这种方法失败了,因为 UI 线程从未收到任何消息。当我将缓冲区大小增加到64 KBytes 时仍然是如此。
工作线程以“最低”优先级运行,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*/);
UI通过类似以下代码接收它们:
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 线程似乎从未接收到缓冲区中的消息,即使传输它们的机制与发布单个报告相同?
64 位 Windows 7、Visual Studio 2010、本机 C++/MFC
WaitForMultipleObjects
函数是用来等待工作线程完成的:WaitForMultipleObjects(nThreadsActive, threadHandles, TRUE/*等待所有线程都完成*/, INFINITE);
- Woody20