我的问题实际上是,如果我在另一个线程中编写一个变量,然后PostMessage到一个Wnd,UI线程中的GetMessage是否会与它同步,并且我可以安全地读取该变量?
背景是:我想使用PostMessage从后台线程更新UI,并且担心数据竞争。我是否需要其他同步实用程序?
谢谢。
编辑:标题非常混乱,所以请更改它。
更详细地说:假设我想更新一个std::string,它是一个全局变量。因为我在PostMessage之前更新了string,所以我可以安全地在处理该消息的Window Proc中读取string吗?
我熟悉C++11多线程术语,如happens-before、sequence-before、synchronize-with和release-acquire概念,所以我的问题可以用另一种方式回答:
在读取之前写入string会发生吗?
PS:假设这是一次性的事情,工作线程不会一次又一次地更新string。
发布于 2013-12-22 15:28:11
Windows消息队列是线程安全的生产者-消费者队列。MSG结构被复制到队列中,因此一旦消息被发布,您就可以重新加载自己的消息数据并再次PostMessage,而不会出现问题。
当开发人员将指针/引用PostMessage为wParam、lParam时,会出现生命周期问题。如果指针指向一个本地堆栈对象,那么在接收GetMessage/wndProc中处理指向它的指针之前,它可能会被释放。类似地,如果指向用new实例化的对象的指针在GetMessage线程中处理之前在posting线程中被显式删除。
如果您提供更多关于您的PostMessaging数据的详细信息,我们应该能够给您提供建议。
发布于 2013-12-22 18:05:11
不是的。你对此的控制是零。PostMessage是真正的异步的,当消息被处理时,这两个线程中已经发生了许多事情(包括处理先前发布的消息和发送的消息(通过SendMessage)。
根据您要执行的操作,您可以:
malloc/new)和PostMessage ( wParam或lParam)SendMessagePostMessage和SendMessage传输数据拷贝发布于 2013-12-22 20:06:28
它向您保证UI线程将使用数据,并且可以安全地更新窗口。这就结束了,您仍然有另一个线程正在从一个写入数据的线程读取数据,因此需要正常的互锁来确保UI线程不会读取更改的数据。
这是一个非常常见的问题,您无法确切知道UI线程何时检索消息。如果UI线程陷入停顿,可能需要很长时间。因此,除非您显式地握手,否则您无法知道工作线程何时可以继续更新数据,或者何时可以发布另一条消息。创建数据的深层副本可以解决这个问题。或者你需要一个自动重置事件来握手,要当心它会导致死锁。
您必须处理的另一种可能的失败模式是PostMessage()可能失败。当UI线程由于任何原因而停滞时就会发生这种情况,只要消息队列大小超过配额(默认情况下是10,000条消息),您就会得到一个假返回。你对此无能为力,只能睡一会儿,然后再试一次。
当遇到消防问题时,您也可以调用这种失败模式,工作线程生成数据的速度比UI线程所能跟上的速度还要快。消防特别棘手,因为当您使用有限的数据集启动或调试程序时,这种情况很少发生。诊断是丢失WM_PAINT通知,您的UI似乎冻结,即使它仍然是活动的,并积极处理积压的发布消息。您可以通过保持UI更新速度远远低于人眼可以感知的速度来避免这种情况。这很好而且很慢,当你每秒更新超过25次时,所有这些都会变得不可读的模糊。
https://stackoverflow.com/questions/20726430
复制相似问题