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 线程亲和性的主要内容,如果未能解决你的问题,请参考以下文章

Pyqt5 Qtimer理解

QTimer 只能用于以 QThread 启动的线程

QTimer 不触发(触发)超时

python 多线程 QTimer实现多线程

使用 QTimer、QThread 和进度条

在 QThread 中启动 QTimer