C ++如何触发PostMessage在另一个线程中进行

C++ How can i trigger that a PostMessage was proceed in another thread

我有一个 MFC-C++ 应用程序,其中至少有两个线程 运行 "MainFrame"(=GUI 线程)和一个 "Solver" 线程。

在某一时刻,第二个线程(求解器)启动了模型的更改,GUI 线程应由 PostMessage(...) 执行。为了安全起见,我想等待该消息在第二个线程中继续。

通过使用 SendMessage(...) Solver 线程等待消息被执行,但通过这种方式我们绕过了不应该成为目标的消息队列。

我的问题:在我继续之前,如何正确清理check/trigger我的消息已处理?

  1. 我们是否需要通过 GetQueueStatus(...) 每 'x' 秒检查一次主线程消息队列的状态?
  2. 有没有办法让主线程发回 "success event" 给另一个线程?第二个等待事件返回?
  3. boost 是否为此类问题提供了简单的解决方案?
  4. 是否已经有类似的问题但我没有找到? (抱歉)

我的函数:

void PostSequencerMessageToGUI(ESequencerSignal signal, CSchedulerStep * step)
{
    CMainFrame *mainFrame = theApp.GetMainFrame();
    assert(mainFrame);
    if (!mainFrame)
        return;
    mainFrame->PostMessage(WM_SEQUENCER_SIGNAL, signal, reinterpret_cast<LPARAM>(step));
    // mainFrame->SendMessage(WM_SEQUENCER_SIGNAL, signal, reinterpret_cast<LPARAM>(step));

    // Message was posted, now wait for event back to continue procedure
    // ... but how? ...and when to cancel ? ...
    return; 
}

由于 SendMessage 忽略当前消息队列(它传递队列),我无法使用这种方法。

我在另一个问题中找到了我的解决方案,它是使用 条件变量 Mutex 解决的。

我的解决方案:

#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
boost::condition_variable g_sequencerJobCondition;
boost::mutex g_guiMutex;

void PostSequencerMessageToGUI(ESequencerSignal signal, CSchedulerStep * step)
{
    CMainFrame *mainFrame = theApp.GetMainFrame();
    assert(mainFrame);
    if (!mainFrame)
        return;

    bool work_is_done = false;

    try {
        boost::mutex::scoped_lock lock(g_guiMutex);
        mainFrame->PostMessage(WM_SEQUENCER_SIGNAL, reinterpret_cast<WPARAM>(&work_is_done), reinterpret_cast<LPARAM>(step));

        // Message was posted, now wait for event back to continue procedure
        while (!work_is_done){
            g_sequencerJobCondition.wait(lock);
        }
    } 
    catch (... /*e*/){
        // Handle all kind of exception like boost::thread_resource_error, boost::thread_interrupted, boost::exception, std::exception
        // ...
    }
    // ...
    return;
}

LRESULT CMainFrame::OnSequencerPostMessage( WPARAM wParam, LPARAM lParam )
{
    // ...
    bool *work_is_done = reinterpret_cast<bool*>(wParam);
    CSchedulerStep* step = reinterpret_cast<CSchedulerStep*>(lParam);

    // Handle business case ...
    // ...

    // Finally notify sequencer thread that the work is done
    work_is_done = true;
    g_sequencerJobCondition.notify_one();

    return true;
}