我在尝试从其他线程使用 WIN32 API 时遇到死锁。我的应用程序中需要额外的线程来提高帧速率。它实际上有帮助,但是,我在几乎所有系统功能中都遇到了死锁:
::ShowWindow ::MoveWindow ::UpdateWindow
我知道例如 ShowWindow() 可以替换为 ShowWindowAsync() 并且它确实解决了问题,但是在 MoveWindow() 和 UpdateWindow() 中没有这样的替代方案。
有人遇到过这些问题吗,解决办法是什么?
谢谢!
我在尝试从其他线程使用 WIN32 API 时遇到死锁。我的应用程序中需要额外的线程来提高帧速率。它实际上有帮助,但是,我在几乎所有系统功能中都遇到了死锁:
::ShowWindow ::MoveWindow ::UpdateWindow
我知道例如 ShowWindow() 可以替换为 ShowWindowAsync() 并且它确实解决了问题,但是在 MoveWindow() 和 UpdateWindow() 中没有这样的替代方案。
有人遇到过这些问题吗,解决办法是什么?
谢谢!
您引用的所有 API 函数的共同点是它们向目标窗口发送(!)一些消息。UpdateWindow 可能是最明显的,因为它需要发送 WM_PAINT。另请注意,它“发送”消息并且不发布到队列中(对于 UpdateWindow,MSDN 文档明确指出了这一点,对于其他人可能不太明显)。
另请注意,某些评论中提到了窗口具有线程关联性。除其他外,这意味着该窗口的消息仅在一个线程上接收/发送。如果您将消息发送到另一个线程的窗口,操作系统将负责确定何时应该发送该消息(即调用窗口过程)。这(调度传入的已发送消息)仅发生在某些 API 调用期间,在此期间可以假定使用随机消息调用窗口过程是安全的。相关时间是在 GetMessage 和 PeekMessage* 期间。
因此,如果您的窗口拥有线程(也称为 UI 线程)正常泵送消息,则传入的已发送消息也会快速分派。但是,从您的问题看来,您的 UI 线程目前很忙。如果第二个线程然后调用其中一个所述函数,那么它将阻塞,直到第一个线程提供一个机会来分派发送的消息。
正如其他人所说,将用户界面代码保留在一个专用的 UI 线程上通常是一个好主意(尽管例外 - 一如既往 - 证明了规则)。并且绝对有必要(为了获得良好的用户体验)让窗口拥有线程始终响应消息。如果您的 UI 线程还必须等待一些同步对象,您可能会发现 MsgWaitForMultipleObjects 很有帮助。
*该列表可能不完整。
术语“死锁”描述了一个非常具体的事情,两个线程等待访问被另一个锁定的资源。没有迹象表明您的情况正在发生这种情况(或者是否存在?),那么您正在经历的究竟是什么?另外,你想用多线程实现什么?
在任何情况下,将 UI 保持在单个线程中,使用 SendMessage() & Co 通知该线程后台线程中发生的任何事件。或者,您也可以使用计时器来轮询某些状态更改。这样,您就安全了,您的应用程序不应该被锁定(至少不是因为使用来自不同线程的 UI)。
更准确地说,您必须将窗口及其所有子窗口的消息循环保留在单个线程中。您可以创建多个窗口并从它们自己的线程处理每个窗口,但不要混合调用。但实际上,这种区别并不重要,因为很少有应用程序会创建多个窗口(不,例如消息框或其他对话框不算在内)。