简体   繁体   English

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

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

I have a MFC-C++ application where at least two threads are running "MainFrame" (=GUI thread) and a "Solver" thread. 我有一个MFC-C ++应用程序,其中至少有两个线程正在运行“MainFrame”(= GUI线程)和一个“Solver”线程。

At one point the second thread (Solver) initiate a change in the model which the GUI thread should execute by a PostMessage(...) . 在某一点上,第二个线程(Solver)启动模型的更改,GUI线程应该由PostMessage(...)执行。 To be safe I want to wait that message was proceeded to continue in the second thread. 为了安全起见,我想等待该消息继续在第二个线程中继续。

By using a SendMessage(...) the Solver thread waits for the message to be executed but in this way we bypass the message queue which shouldn't be the goal. 通过使用SendMessage(...) ,Solver线程等待消息被执行,但这样我们绕过了不应该成为目标的消息队列。

My question: How can I properly and clean check/trigger that my message was proceed before I continue? 我的问题:在继续之前,我怎样才能正确清理检查/触发我的信息是否继续?

  1. Did we need to check every 'x' seconds the status of the main thread message queue by GetQueueStatus(...) ? 我们是否需要通过GetQueueStatus(...)检查每个'x'秒主线程消息队列的状态?
  2. Is there a way to have the main thread send back a "success event" to the other thread? 有没有办法让主线程将“成功事件”发送回另一个线程? And that the second one waits to have an event back? 而第二个等待事件回来?
  3. Did boost provide an easy solution for this kind of problems? 增强是否为这类问题提供了简单的解决方案?
  4. Was there already a similar question which i didn't found? 是否已经有类似的问题,我没有找到? (sorry) (抱歉)

My function: 我的功能:

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

As SendMessage is ignoring the current message queue (it pass the queue) i couldn't use this approach. 由于SendMessage忽略了当前的消息队列(它通过了队列),我无法使用这种方法。

I found my solution in another question where it is solved using a Condition variables and a Mutex . 我在另一个问题中找到了我的解决方案,使用Condition变量Mutex解决它。 https://stackoverflow.com/a/16909012/5036139 https://stackoverflow.com/a/16909012/5036139

My solution: 我的解决方案

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

And

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM