为啥我的 DCOM 客户端会锁定对 SendMessage 的调用?

Posted

技术标签:

【中文标题】为啥我的 DCOM 客户端会锁定对 SendMessage 的调用?【英文标题】:Why is my DCOM client locking on a call to SendMessage?为什么我的 DCOM 客户端会锁定对 SendMessage 的调用? 【发布时间】:2010-02-23 17:48:56 【问题描述】:

在 XP 上运行。我有一个调用CoInitializeEx(NULL, COINIT_MULTITHREADED) 的客户端,加载一个(本地)DCOM 对象,并附加一个事件接口,以便DCOM 对象可以发回事件。客户端看起来很像记事本,带有覆盖客户区域的多行文本框以显示事件消息。以下是造成锁定的调用:

客户端在 DCOM 对象上调用 p->DoStuff()。 DCOM 对象在处理DoStuff() 时在客户端调用c->DoStuffEvent()。 客户端向子文本框发送EM_REPLACESEL 消息,使其显示“正在发生的事情”

客户端冻结在SendMessage(EM_REPLACESEL)。客户端对p->DoStuff() 的调用在主线程上完成,而SendMessage(EM_REPLACESEL) 在不同线程上完成。我确定这与问题有关。

谁能解释导致锁定的原因以及我可以如何解决它?客户端和 DCOM 对象由我在 MSVC/ATL 中编码,因此我可以根据需要修改它们。

【问题讨论】:

【参考方案1】:

看起来窗口是由主线程创建的。所以这是唯一可以调用窗口过程的线程。当你从另一个线程SendMessage 时,它实际上将消息放入主线程的队列,然后等待主线程调用GetMessagePeekMessage。在对GetMessagePeekMessage 的调用中,Windows 注意到一个等待的交叉线程SendMessage 并将该消息传递给窗口进程,然后唤醒第二个线程并让它继续。

如果你不关心SendMessage(EM_REPLACESEL)的返回值,你可以用SendNotifyMessage代替。但是如果你这样做,你需要确保你通过EM_REPLACESEL消息传递的字符串在消息最终被传递时仍然有效。

【讨论】:

是的,现在这很有意义。谢谢。【参考方案2】:

根据SendMessage 文档,SendMessage 在函数完成之前不会返回。它是同步的。我相信它也总是在 UI 线程上得到回答。如果你想做一个异步消息传递,那么你应该使用PostMessage。

【讨论】:

以上是关于为啥我的 DCOM 客户端会锁定对 SendMessage 的调用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Service Fabric 代码会锁定自己的 PDB?

为啥我的 PDF 生成进程会锁定我站点中的其他 ajax 进程?

为啥hibernate关闭连接后h2的数据库文件仍然会被锁定一段时间?

电脑上面现实OSD已锁是啥意思,显示器为啥会自动关闭

从 COM 到 DCOM

为啥 MVCC 需要对 DML 语句进行锁定