Windows 如何使用postThreadMessage传递结构
我想使用windows的消息队列功能将结构发送到另一个线程。 但是我发现postthreadmessage函数只提供了两个整数参数,lparam和wparam供我传递参数,所以我决定将结构的地址放在lparam中。这是windows传递struct的正确方法吗Windows 如何使用postThreadMessage传递结构,windows,boost,message-queue,shared-ptr,Windows,Boost,Message Queue,Shared Ptr,我想使用windows的消息队列功能将结构发送到另一个线程。 但是我发现postthreadmessage函数只提供了两个整数参数,lparam和wparam供我传递参数,所以我决定将结构的地址放在lparam中。这是windows传递struct的正确方法吗 我打算使用boost::shared_ptr在接收方线程和发送方线程中保存struct的地址。我怀疑当两个共享的ptr超出范围时,结构会被释放两次吗?我想不出一种方法来确保堆上分配的结构将100%释放,有什么想法吗 对于第一个问题,是的,
我打算使用boost::shared_ptr在接收方线程和发送方线程中保存struct的地址。我怀疑当两个共享的ptr超出范围时,结构会被释放两次吗?我想不出一种方法来确保堆上分配的结构将100%释放,有什么想法吗 对于第一个问题,是的,LPARAM打算用作整数或指针。从定义上可以清楚地看出:
typedef LONG_PTR LPARAM;
这是一个足以容纳指针的整数
关于共享\u ptr,您是对的,如果您传递原始指针并将其包装到另一个共享\u ptr中,您将释放它两次:
shared_ptr<Thing> a;
PostThreadMessage(x, 0, (LPARAM)a.get());
...
LRESULT OnMessage(int msg, WPARAM wp, LPARAM lp)
{
shared_ptr<Thing> p((Thing*)lp); //Bad!!!
}
shared\u ptr a;
PostThreadMessage(x,0,(LPARAM)a.get());
...
LRESULT OnMessage(int msg、WPARAM wp、LPARAM lp)
{
共享的_ptrp((Thing*)lp);//糟糕!!!
}
但您可以尝试以下解决方法:
shared_ptr<Thing> a;
PostThreadMessage(x, 0, new shared_ptr<Thing>(a)); //pointer to smart-pointer
...
LRESULT OnMessage(int msg, WPARAM wp, LPARAM lp)
{
shared_ptr<Thing> *pp = (shared_ptr<Thing>*)lp;
shared_ptr<Thing> p(*pp);
delete pp; //no leak
}
shared\u ptr a;
PostThreadMessage(x,0,新共享的_ptr(a))//指向智能指针的指针
...
LRESULT OnMessage(int msg、WPARAM wp、LPARAM lp)
{
共享_ptr*pp=(共享_ptr*)lp;
共享ptr p(*pp);
删除pp;//无泄漏
}
事后思考:注意PostThreadMessage可能会失败。。。你不想泄露共享的密码
根据我的经验,通常最好使用std::deque保存数据,并使用PostThreadMessage通知那里有数据。这样你就永远不会丢失任何东西!YMMV我在使用Qt
QModelIndex
类时遇到了类似的情况,该类使用void*
保存数据,但我使用共享\u ptr
管理它指向的数据
为了避免直接取消对void*
的引用(可能指向不再存在的对象),我使用了从void*
到weake\ptr
的映射。QModelIndexes
引用的所有对象都存储在地图中。当需要取消对void*
的引用时,我使用void*
键从映射中检索相应的weak\u ptr
,然后将weak\u ptr
转换为共享的ptr
。shared_ptr
要么等于void*
,要么等于NULL
,您还可以获得类型安全性
请注意,我的解决方案不必处理您提到的并发问题,但您可以根据自己的情况对其进行调整。可以使用LPRAM存储指向对象的原始指针,然后使用映射将原始指针转换为智能指针。用互斥锁保护地图,你可能会在那里。是的,当然。比较WM_COPYDATA。只需让接收器释放内存即可。如果接收线程显示任何窗口,甚至没有消息框,请不要使用PostThreadMessage()。@Hans Passant我知道这是一篇旧文章,但您能简要解释一下为什么在这种情况下使用PostThreadMessage()不好吗?可能会有什么后果?是的。但是使用共享数据本身需要显式的线程同步,它会阻塞。我使用消息的原因是因为我想要异步写入,不需要显式锁定操作。我想我可能只是在writer线程中分配内存,然后在reader线程中释放内存,希望PostThreadMessage永远不会失败……事后思考:使用指向
弱\u ptr
的指针如何。泄漏弱\u ptr
要比泄漏共享\u ptr
好得多,只要消息的发送者挂起共享\u ptr a
,当接收者需要时,该对象仍然存在。我看到PostThreadMessage仅在两种情况下失败:a)目标队列已满(我计算了大约40000条消息,但没有记录限制,因此它可能取决于许多参数);以及b)目标线程尚未创建消息队列。线程第一次使用函数访问队列时会自动创建队列(例如,GetMessage
)。因此,如果您创建线程,并且在调用PostThreadMessage
之后,它可能会失败。为了安全起见,只需检查返回值:PostThreadMessage
如果失败,则返回FALSE
。