C++ MFC数据通过PostMessage转发到主线程

C++ MFC数据通过PostMessage转发到主线程,c++,visual-studio-2010,mfc,postmessage,C++,Visual Studio 2010,Mfc,Postmessage,我有一个C++/MFC应用程序需要重构。该应用程序用于处理主线程上的大部分数据,因此会阻止输入,现在我想将其更改为所有GUI更新都通过PostMessage完成 不幸的是,我似乎找不到一个关于如何实现这一目标的好来源 现在,我正在考虑创建一个优先级队列,用critical section保护,一个处理这个队列的工作线程(while(true)),以及一个将指向数据的指针发送到主线程的PostMessage机制 这种方法让我害怕的是,PostMessage根本不能保证到达主线程,因此,如果我理解正

我有一个C++/MFC应用程序需要重构。该应用程序用于处理主线程上的大部分数据,因此会阻止输入,现在我想将其更改为所有GUI更新都通过PostMessage完成

不幸的是,我似乎找不到一个关于如何实现这一目标的好来源

现在,我正在考虑创建一个优先级队列,用critical section保护,一个处理这个队列的工作线程(while(true)),以及一个将指向数据的指针发送到主线程的PostMessage机制


这种方法让我害怕的是,PostMessage根本不能保证到达主线程,因此,如果我理解正确,就有可能发生内存泄漏

第二个问题是,另一个应用程序可以向我的应用程序发送自定义消息,而我的应用程序可能尝试将WPARAM或LPARAM作为指针取消引用,从而导致AV

有人知道这类任务的最佳实践是什么吗


数据可以是用于web控件的HTML内容,也可以是用于列表框、下拉列表等的其他内容。

使用两个队列,一个用于工作线程的工作请求,另一个用于返回主线程的结果。您可以使用PostMessage唤醒主线程并告诉它检查队列,但消息中不需要任何参数。

我不久前解决了一个类似的问题。我创建了一个单例队列来保存需要从后台线程流向UI(主)线程的数据(或操作)。队列由一个关键部分保护。后台线程将其数据放入队列并发布消息。该消息不包含任何数据,它充当一个简单的叫醒电话“嘿,主线程,看看队列,有你的工作”


这样,您就不会有泄漏任何内存或其他资源的风险;可以安全地销毁队列及其包含的所有数据。

您的消息将到达那里。我不知道你为什么认为PostMessage不能保证有效——它确实有效。(编辑:假设PostMessage()返回TRUE!检查返回代码!)

您希望避免使用队列在线程之间通信数据。两个线程访问的任何队列都需要受到保护。在两侧添加硬锁将序列化应用程序

相反,使用包含您的数据的
new
在堆上创建一个数据结构,然后告诉另一个线程“我已经为您获取了数据,它就在这里。”然后接收线程获得该数据指针的所有权,并负责
删除它。这样做,没有硬锁

现在唯一的诀窍是找出“告诉另一个线程”的部分,但这也很容易

如果要将数据从工作线程发送到主线程,只需使用
PostMessage()

worker\u thread\u proc()
{
// ..
//创建要传递给MT的数据对象
MyData*data=新的MyData;
数据->某些值;
//通过它:
PostMessage(main\u wnd,WM\u YOU\u HAVE\u DATA,reinterpret\u cast(DATA),0);
}
…主线程对此进行处理,然后删除数据:

MainWnd::OnYouHaveData(WPARAM wp, LPARAM)
{
  std::auto_ptr<MyData> data(reinterpret_cast<MyData*>(wp));
  my_widget->set_text(data->some_value_); // you get the idea
}
MainWnd::OnYouHaveData(WPARAM wp,LPARAM)
{
标准::自动ptr数据(重新解释铸件(wp));
我的小部件->设置文本(数据->某些值);//你明白了
}
如果您担心外部应用程序的自定义消息会撞到您的消息,您可以让Windows使用为您的消息选择一个唯一的消息ID,您在这里面临的唯一挑战是为您的消息选择正确的名称

如果您正在将数据从主线程发送到工作线程,您可以执行与上述相同的操作,除了不使用
PostMessage()
通过墙发送数据外,您可以使用(确保您的工作线程处于可警报的等待状态--读取链接文档中的备注)或

编辑: 根据您在OP中的评论,现在我明白您为什么担心PostMessage()不起作用了

是的,Windows消息队列大小有一个硬限制。默认情况下,队列中只能有4000条消息。(注册表设置最多可以调整10000)

如果队列已满,则对
PostMessage()
的任何调用都将失败,并显示错误代码。当您检查GetLastError()时(我不记得它现在返回的是哪个错误代码),很明显消息队列已满


听起来不像母鸡,但您确实需要检查API调用的返回值。但除此之外,如果您在消息队列上限中运行,我会说您的应用程序无论如何都是坏的。当队列已满时,应用程序将无法呼吸。屏幕无法绘制,您所做的任何处理都会过时,并且会发生各种不好的事情。如果您正处于这种情况,您可能需要了解原因。

“PostMessage根本不能保证到达主线程”嗯?数据需要从主线程->工作线程、工作线程->主线程,还是两者都需要?如果我理解正确,那么如果MessageQueue超过10000条消息,如果注册表被修改,则可能发生错误。但找不到确切的内容。主要是worker->main。另一个方向可以用简单的参数覆盖。@Madman:啊,是的,你是对的,windows消息队列大小有一个硬限制。但如果你遇到了这种情况,你真的应该看看原因。你的应用程序不会有空闲时间,会停止运行,不会更新屏幕,各种各样的糟糕事情都会发生。太可怕了。您序列化了两个线程,从而抵消了使用多核所带来的所有好处,同时大大增加了复杂性。不,您不必序列化线程。关键的一点是,仅当从队列中提取命令实例时才保持队列锁,然后释放锁,以便后台线程可以继续添加到队列中而无需等待。巴克
MainWnd::OnYouHaveData(WPARAM wp, LPARAM)
{
  std::auto_ptr<MyData> data(reinterpret_cast<MyData*>(wp));
  my_widget->set_text(data->some_value_); // you get the idea
}