C++ C++;如何触发另一个线程中的PostMessage
我有一个MFC-C++应用程序,其中至少有两个线程运行“MainFrame”(=GUI线程)和一个“Solver”线程 在某一点上,第二个线程(解算器)启动模型中的更改,GUI线程应通过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(
PostMessage(…)
执行该更改。为了安全起见,我想等待消息在第二个线程中继续
通过使用SendMessage(…)
解算器线程等待执行消息,但通过这种方式,我们绕过了不应该成为目标的消息队列
我的问题:在我继续之前,我如何正确和干净地检查/触发我的消息是否继续
GetQueueStatus(…)
每隔“x”秒检查一次主线程消息队列的状态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;
}