【发布时间】:2015-06-25 16:52:09
【问题描述】:
如果我启动 QTimer 以固定间隔触发,但插槽对超时信号作出反应,会比另一个计时器间隔更长时间地阻塞主循环。是否会在事件循环再次运行时将 timout 信号堆叠在 Qt 主事件循环上并一个接一个地处理?
如果是,如果多个超时事件堆叠在事件队列上,但计时器在处理之前被停用,会发生什么情况?
【问题讨论】:
如果我启动 QTimer 以固定间隔触发,但插槽对超时信号作出反应,会比另一个计时器间隔更长时间地阻塞主循环。是否会在事件循环再次运行时将 timout 信号堆叠在 Qt 主事件循环上并一个接一个地处理?
如果是,如果多个超时事件堆叠在事件队列上,但计时器在处理之前被停用,会发生什么情况?
【问题讨论】:
如果QTimer 对象和信号接收器属于一个线程,则不会发生排队。 timeout() 信号在控制流进入事件循环之前不会(也不能)再次发送,并且直到插槽完全执行后才会发生(除非在插槽中调用QApplication::processEvents,这可以将其变成一团糟)。但是,如果您的插槽执行时间超过计时器的时间间隔,一旦事件循环空闲,timeout() 将被发送,因此您的插槽将立即再次被调用。但是QTimer 不会发送两个比其间隔更近的timeout() 信号。
如果QTimer 在另一个线程中,并且该线程没有忙于其他事情,它会定期发送timeout() 信号,而不管另一个线程中的槽有多好。这就是 Qt 的信号槽系统的用武之地。它将对发出的信号进行排队。如果您的插槽很慢,它会毫不拖延地多次调用它。如果您停止计时器,它不会撤消已发送的信号,并且可能会在它之后多次调用插槽。此外,如果您停止计时器,则总是有可能此时正在发送另一个信号,并且您的插槽将再次被调用。
如果您希望在插槽调用之间有严格的间隔,而不管插槽的执行时间如何,您应该使用单次计时器。在您的插槽结束时,启动一个单次计时器。当它超时时,它将调用您的插槽并停用,因此您可以在插槽结束时再次启动它。
如果您的程序逻辑取决于计时器的状态,您应该检查计时器在您的槽开始时是否处于活动状态。不保证在执行槽时计时器处于活动状态。
【讨论】: