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