【问题标题】:Should a win32 program always be multi-threadedwin32 程序是否应该始终是多线程的
【发布时间】:2014-02-27 09:24:03
【问题描述】:
现在我正在编写一个每个窗口有 2 个线程的 win32 / opengl 应用程序。一个线程处理 opengl 绘图,另一个处理 windows 消息事件。我的问题是,我应该只对所有 Windows 消息使用 1 个线程吗?会不会导致windows偶尔不响应等问题?
我正在使用多个 Windows 消息循环,都在不同的线程上。在我看来,消息循环是为 1 个线程设计的,并且在一个进程中只出现一次。这是正确的吗?
【问题讨论】:
标签:
c++
multithreading
winapi
opengl
【解决方案1】:
我应该只对所有 Windows 消息使用 1 个线程吗?
你可以,也可以不。它不是由操作系统强制执行的,但可能是由您的 GUI 框架强制执行的。
会不会导致windows偶尔不响应等问题?
它本身不会导致该问题。响应不佳的消息循环通常是由于在处理来自 OS UI 驱动程序的消息的窗口的 wndprocs/event-handlers 中执行过多的工作,或者实际上在它们中等待某些东西而不是及时返回到 GetMessage 调用。操作系统检测到来自 KB 等的消息没有得到处理,并倾向于显示窗口并通常抱怨“没有响应”的应用程序。
如果 WMQ 用于与不处理 UI 消息的线程通信,例如,消息编号为 WM_APP 向上的线程,如果处理此类消息的线程在获取之前执行冗长和/或阻塞操作,操作系统将不执行任何操作回到它的 GetMessage 调用。
在我看来,消息循环是为 1 个线程设计的,并且
一个过程中只出现一次。这是正确的吗?
不,不是。
Windows 消息队列和相关的 GetMessage() 循环可以并且经常用于在进程的线程之间进行通信。 WMQ 是专门的生产者-消费者队列,主要设计用于传递 GUI 消息。因此,它们对消息格式有限制,一个队列只能等待一个线程,但可以使用 WMQ 在非 GUI 线程之间进行通信。
窗口绑定到创建它们的线程是正确的,并且许多 GUI 框架的设计/编写方式使得从多个线程中使用它们是不安全的,但是许多 Windows 消息队列和消息-一个进程中的处理程序当然是可能的。
【解决方案2】:
这取决于实现。如果独立进程不应该干扰程序流,多线程通常是有意义的。然而,也有其他方法可以实现类似的事情。例如。您可以使用计时器将流程中断几毫秒并执行其他线程将执行的操作。
如果您意识到您的窗口事件线程正在达到其极限,那么我首先会想到,您可能不仅在进行事件处理,而且还进行了更大的计算。在那里开始一个新线程是有意义的。
编辑:我不是 Windows 专业人士。但是我所知道的几乎所有实现都只用于事件系统一个线程(循环)。 Qt 有一些优雅的方法来规避中断并通过以不同方式产生新线程来扩展事件系统。它还支持与定时器结合使用的信号/插槽。也许你有兴趣使用它。