2

我在线程 A 上有一个窗口,它在某些时候(由于在其 wndproc 上接收到消息)触发线程 B 上的操作,然后等待操作完成(使用某种同步机制)。线程 B 然后调用MoveWindow(), 以在线程 A 的窗口(例如标准文本框)内移动子窗口。此时程序由于某种原因进入死锁状态。如果MoveWindow()从线程 A 调用,一切正常。任何想法为什么?

4

5 回答 5

4

You could use SetWindowPos with the flag SWP_ASYNCWINDOWPOS, instead of MoveWindow.

The reason may be that ThreadA waits for ThreadB to handle some event but meanwhile ThreadB wait for ThreadA (the thread owning the window) to return the result of MoveWindow.

于 2009-04-21T13:10:50.150 回答
2

我认为@1800 的解释是最接近的。

当您从不拥有该窗口的线程中移动一个窗口时,我认为 Windows 不会使用 SendMessage 将 WM_WINDOWPOSCHANGING 之类的东西传递给移动窗口的窗口过程。相反,为了确保仅在正确的线程上调用窗口过程,它会发布 WM_WINDOWPOSCHANGING 消息并阻塞,直到它被正确线程中运行的事件循环选中。但是,该事件循环没有运行 - 它被阻塞,等待 MoveWindow 完成。

@totaland 和 @Logan Capaldo 的解决方案将起作用。

可能你不需要等到你的窗口移动了。或者,如果您确实需要确定,请使用 MsgWaitForMultipleObjectsEx 并运行一个小事件循环来处理发布的消息。

于 2009-04-22T00:37:29.627 回答
2

什么是“某种同步机制”?如果是 WaitFor(Multiple)Object(s),可以使用 [MsgWaitForMultipleObjects]( http://msdn.microsoft.com/en-us/library/ms684242(VS.85).aspx) ( Ex代替唤醒当您有消息并按照 Lucero 的建议发送消息时。

于 2009-04-20T23:55:25.757 回答
1

您需要确保在等待时线程的消息泵正在运行。

您可能希望使用PeekMessage()(或者GetMessage())和DispatchMessage()进行循环。

于 2009-04-20T23:44:18.857 回答
1

用户界面对象的线程亲和性,第 1 部分:窗口句柄

不同的对象有不同的线程亲和性规则,但底层原理来自于 16 位 Windows。

最重要的用户界面元素当然是窗口。窗口对象具有线程亲和性。创建窗口的线程是与窗口密不可分的线程。非正式地,有人说线程“拥有”窗口。消息仅在拥有它的线程上发送到窗口过程,一般来说,对窗口的修改只能从拥有它的线程进行。尽管窗口管理器允许任何线程访问诸如窗口属性、样式和其他属性(如窗口过程)之类的东西,并且从窗口管理器的角度来看,此类访问是线程安全的,但通常应该限制加载-修改-写入序列到所有者线程。

于 2009-04-21T00:25:21.443 回答