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

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

本文关键字:线程 另一个 何触发 PostMessage C++      更新时间:2023-10-16

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

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

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

我的问题是:在继续之前,我如何正确、干净地检查/触发我的消息是否继续?

  1. 我们是否需要通过GetQueueStatus(...)每隔"x"秒检查一次主线程消息队列的状态
  2. 有没有办法让主线程向另一个线程发送"成功事件"?第二个在等待一个事件回来
  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忽略了当前消息队列(它通过了队列),我无法使用这种方法。

我在另一个问题中找到了我的解决方案,该问题使用条件变量互斥来解决。https://stackoverflow.com/a/16909012/5036139

我的解决方案:

#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;
}