工作线程如何与主 UI 线程通信?

Woo*_*y20 5 c++ mfc multithreading

工作线程与主 UI 线程通信的最佳方式是什么?

摘要: 我的 C++/MFC 应用程序是基于对话框的。为了进行长时间的计算,主 UI 线程创建了多个工作线程。当工作线程在计算中取得进展时,它们会将进度报告给主 UI 线程,然后主 UI 线程会显示进度。

这对于数字进度值来说效果很好,这些值位于共享内存中(由工作人员写入,由 UI 读取),但我在处理文本进度消息时遇到了问题。我尝试的解决方案已经经历了多次迭代,但似乎都不起作用。

  1. 我让 UI 线程将控件指针传递给工作人员,工作人员直接更新 UI。这不是很有效,而且似乎是错误的方法。

  2. 我让工作人员使用 SendMessage 向 UI 线程的窗口发送消息。这就陷入了僵局。(在处理消息之前 SendMessage 不会返回。)

  3. 与 (2) 相同,但使用 PostMessage 发送到 UI 线程的窗口。这在一段时间内有效,然后消息就丢失了。(PostMessage 立即返回。)进一步调查显示,消息队列的配额(默认为 10,000)已被超出。

  4. 我增加了消息队列的配额(注册表中的变量 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\USERPostMessageLimit),但丢失消息的数量没有改变。

  5. 我让每个工作线程在 4 KB 缓冲区中缓冲消息,并在缓冲区填满时发送 PostMessage。此操作失败,因为 UI 线程从未收到任何消息。当我将缓冲区大小增加到 64 KB 时,情况也是如此。

工作线程以“最低”优先级运行,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*/);
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 在可能出现数千条文本报告的情况下,工作人员发布进度报告的首选方式是什么?

  2. 为什么我无法增加队列中发布消息的配额?

  3. 为什么主 UI 线程似乎从未收到缓冲区中的消息,即使传输消息的机制与发布各个报告相同?

64 位 Windows 7、Visual Studio 2010、本机 C++/MFC

Sco*_*MVP 4

当主线程处于 WaitForMultipleObjects 调用中时,不会处理任何消息,也不会更新任何控件或其他窗口。解决方案是:不要这样做。