SetWindowText 引起的死锁

💡 原文中文,约3500字,阅读约需9分钟。
📝

内容提要

在Windows程序中,线程通常通过循环处理消息。sokol_app的回调函数在WinProc中被动调度,导致黑屏问题。虽然通过锁同步任务解决了部分问题,但在改变窗口标题时出现死锁。最终发现,调用SetWindowTextW在不同线程中会导致消息阻塞,需在窗口线程中直接调用以避免死锁。

🎯

关键要点

  • Windows程序中的线程通常通过循环处理消息。
  • sokol_app的回调函数在WinProc中被动调度,导致黑屏问题。
  • 使用锁同步任务解决了部分问题,但在改变窗口标题时出现死锁。
  • 调用SetWindowTextW在不同线程中会导致消息阻塞,需在窗口线程中直接调用以避免死锁。
  • 在多线程设计中,窗口只是多线程任务的一部分,需要更高阶的框架来调度任务。
  • ltask的任务在lua虚拟机上运行,C层与其隔离,避免了线程间的stack问题。
  • sokol的设计并未考虑多线程,可能隐藏多线程bug。
  • 通过锁同步任务的方案在大多数场景中有效,但在启动时偶尔出现死锁。
  • 死锁的原因是窗口标题的改变在不同线程中调用SetWindowTextW导致的。
  • 解决方案是在窗口线程中调用SetWindowTextW,避免消息进入消息队列。
  • PostWindowTextW无法使用,因为它涉及字符串生命周期管理问题,Windows禁止发送此类消息。

延伸问答

SetWindowTextW导致死锁的原因是什么?

死锁的原因是因为在不同线程中调用SetWindowTextW时,WM_SETTEXT消息被投递到窗口消息处理线程,导致消息阻塞。

如何避免在Windows程序中使用SetWindowTextW引起的死锁?

可以在窗口线程中直接调用SetWindowTextW,以避免消息进入消息队列,从而避免死锁。

sokol_app在多线程设计中存在哪些问题?

sokol_app并未考虑多线程,可能隐藏多线程bug,且其回调函数在WinProc中被动调度,导致线程管理不友好。

在使用ltask框架时,如何处理窗口标题的改变?

在使用ltask框架时,应避免在frame callback中改变窗口标题,而是应在窗口线程中处理该操作。

使用锁同步任务的方案在什么情况下会出现死锁?

在启动程序时,偶尔会出现死锁,尤其是在锁未解开时,导致frame callback无法返回。

为什么PostWindowTextW无法用于改变窗口标题?

因为PostWindowTextW涉及字符串生命周期管理问题,Windows禁止发送此类消息以避免错误。

➡️

继续阅读