Windows 如何使用postThreadMessage传递结构

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%释放,有什么想法吗 对于第一个问题,是的,

我想使用windows的消息队列功能将结构发送到另一个线程。 但是我发现postthreadmessage函数只提供了两个整数参数,lparam和wparam供我传递参数,所以我决定将结构的地址放在lparam中。这是windows传递struct的正确方法吗


我打算使用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