C++ C++;如何触发另一个线程中的PostMessage

C++ C++;如何触发另一个线程中的PostMessage,c++,multithreading,visual-c++,mfc,message-queue,C++,Multithreading,Visual C++,Mfc,Message Queue,我有一个MFC-C++应用程序,其中至少有两个线程运行“MainFrame”(=GUI线程)和一个“Solver”线程 在某一点上,第二个线程(解算器)启动模型中的更改,GUI线程应通过PostMessage(…)执行该更改。为了安全起见,我想等待消息在第二个线程中继续 通过使用SendMessage(…)解算器线程等待执行消息,但通过这种方式,我们绕过了不应该成为目标的消息队列 我的问题:在我继续之前,我如何正确和干净地检查/触发我的消息是否继续 我们是否需要通过GetQueueStatus(

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

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

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

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

  • 我们是否需要通过
    GetQueueStatus(…)
    每隔“x”秒检查一次主线程消息队列的状态
  • 有没有办法让主线程将“成功事件”发回给另一个线程?第二个等待事件返回
  • boost是否为此类问题提供了简单的解决方案
  • 是否已经有一个我没有发现的类似问题?(对不起)
  • 我的职能:

    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; 
    }
    
    void PostSequencerMessageToGUI(ESequencerSignal信号,CSSchedulerStep*步骤)
    {
    CMainFrame*mainFrame=theApp.GetMainFrame();
    断言(大型机);
    如果(!大型机)
    返回;
    大型机->后消息(WM_SEQUENCER_信号,信号,重新解释_cast(步骤));
    //大型机->发送消息(WM_SEQUENCER_信号、信号、重新解释_cast(步骤));
    //消息已发布,现在等待事件返回以继续此过程
    //…但如何取消?…以及何时取消。。。
    返回;
    }
    
    由于SendMessage忽略了当前的消息队列(它通过了队列),因此我无法使用此方法

    我在另一个问题中找到了我的解决方案,其中使用条件变量和互斥体来解决。

    我的解决方案:

    #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;
    }
    
    #包括
    #包括
    boost::条件\变量g\ u sequencerObjCondition;
    boost::mutex g_guiMutex;
    无效PostSequencerMessageToGUI(ESequencerSignal信号,CSSchedulerStep*步骤)
    {
    CMainFrame*mainFrame=theApp.GetMainFrame();
    断言(大型机);
    如果(!大型机)
    返回;
    bool work\u is\u done=false;
    试一试{
    mutex::作用域锁定锁(g_guiMutex);
    mainFrame->PostMessage(WM_SEQUENCER_信号、重新解释_cast(&work_完成)、重新解释_cast(步骤));
    //消息已发布,现在等待事件返回以继续过程
    当(!工作完成时){
    g_sequencerJobCondition.等待(锁定);
    }
    } 
    捕获(…/*e*/){
    //处理所有类型的异常,如boost::thread\u resource\u error、boost::thread\u interrupted、boost::exception、std::exception
    // ...
    }
    // ...
    返回;
    }
    

    LRESULT-CMainFrame::OnSequencerPostMessage(WPARAM-WPARAM,LPARAM-LPARAM)
    {
    // ...
    bool*工作完成=重新解释铸件(wParam);
    CSSchedulerStep*step=重新解释强制转换(LPRAM);
    //处理商业案例。。。
    // ...
    //最后通知sequencer线程工作已完成
    工作完成=正确;
    g_sequencerObjCondition.通知_one();
    返回true;
    }
    
    错误在您的代码中。如果重要的是,无论消息是发布到消息队列,还是直接传递到窗口过程,您都会遇到比此问题更多的严重问题。无论如何,如果您想要类似于
    PostMessage
    的回复,请使用。只需使用线程同步对象,如autoreset事件,即您使用CreateEvent创建的类型。处理完消息后,在UI线程中调用SetEvent()。和工作线程中的WaitForSingleObject()。如果您还需要返回“success”,则将bool或int成员添加到CSchedulerStep。使用CreatEvent和SetEvent可能也会起作用。请将找到的解决方案添加到您的答案中。
    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;
    }