QTimer 线程亲和性
Posted
技术标签:
【中文标题】QTimer 线程亲和性【英文标题】:QTimer thread affinity 【发布时间】:2014-03-11 08:53:23 【问题描述】:在文档中它说:
在多线程应用程序中,您可以在任何线程中使用
QTimer
有一个事件循环。要从非 GUI 线程启动事件循环,请使用QThread::exec()
。 Qt 使用计时器的线程亲和性来确定 哪个线程将发出timeout()
信号。正因为如此,你 必须在其线程中启动和停止计时器;这是不可能的 从另一个线程启动计时器。
所以当我有一个QTimer
对象时,Qt 使用该对象(或它的父级)的线程亲和性来确定哪个线程将发出timeout()
信号。
但是当我使用不需要QTimer
实例的静态成员函数singleShot(..)
时会发生什么,那么哪个线程会发出超时信号?
【问题讨论】:
【参考方案1】:Qt 是开源的,所以最好的方法是检查source code。
所以创建了internal class QSingleShotTimer 的对象(它是QObject
但不是QTimer
)。
回答您问题的最重要的一行是here:
connect(this, SIGNAL(timeout()), receiver, member);
没有moveToThread
,所以它是这样工作的:
-
为当前线程创建临时对象
信号是从那个线程发出的
如果将目标对象分配给同一线程,则会立即调用该槽
否则槽调用将在目标所属线程的事件循环中排队。
请参阅connect 的文档及其5-th parameter (type of connection) 的值。
请注意,如果msec
的值为零,则槽的调用将在接收者所属线程的偶数循环中排队(不创建临时对象)。
【讨论】:
我观察到一个singleShot
计时器从未真正执行它的回调;我还没有制作一个最小的完整示例(因此不值得提出一个新问题),但我猜测它与线程亲和力有关。所以我想知道,在我的 Qt 版本(我认为它是 5.6.2-1)中,singleShot
在错误线程中启动的计时器实际上是否无法触发回调。
我打赌你正在从不会将控制权返回给事件循环的线程调用singleShot
。需要事件循环处理,以便QTimer
可以工作。【参考方案2】:
QTimer::singleShot()
函数创建一个 QTimer 对象并在内部完成所有信号设置和清理工作。
线程亲和性将与正在运行的执行该函数的线程相关。
【讨论】:
你错了,看我的回答。QTimer
没有被创建,而是内部类QSingleShotTimer
的一些对象。以上是关于QTimer 线程亲和性的主要内容,如果未能解决你的问题,请参考以下文章