【问题标题】:QTimer thread affinityQTimer 线程亲和性
【发布时间】:2014-03-11 08:53:23
【问题描述】:

在文档中它说:

在多线程应用程序中,您可以在任何线程中使用QTimer 有一个事件循环。要从非 GUI 线程启动事件循环,请使用 QThread::exec()。 Qt 使用计时器的线程亲和性来确定 哪个线程将发出timeout() 信号。正因为如此,你 必须在其线程中启动和停止计时器;这是不可能的 从另一个线程启动计时器。

所以当我有一个QTimer 对象时,Qt 使用该对象(或它的父级)的线程亲和性来确定哪个线程将发出timeout() 信号。
但是当我使用不需要QTimer 实例的静态成员函数singleShot(..) 时会发生什么,那么哪个线程会发出超时信号?

【问题讨论】:

    标签: qt


    【解决方案1】:

    Qt 是开源的,所以最好的方法是检查source code。 所以创建了internal class QSingleShotTimer 的对象(它是QObject 但不是QTimer)。
    回答您问题的最重要的一行是here

      connect(this, SIGNAL(timeout()), receiver, member);
    

    没有moveToThread,所以它是这样工作的:

    1. 为当前线程创建临时对象
    2. 信号是从那个线程发出的
    3. 如果将目标对象分配给同一线程,则会立即调用该槽
    4. 否则槽调用将在目标所属线程的事件循环中排队。

    请参阅connect 的文档及其5-th parameter (type of connection) 的值。

    请注意,如果msec 的值为零,则槽的调用将在接收者所属线程的偶数循环中排队(不创建临时对象)。

    【讨论】:

    • 我观察到一个singleShot 计时器从未真正执行它的回调;我还没有制作一个最小的完整示例(因此不值得提出一个新问题),但我猜测它与线程亲和力有关。所以我想知道,在我的 Qt 版本(我认为它是 5.6.2-1)中,singleShot 在错误线程中启动的计时器实际上是否无法触发回调。
    • 我打赌你正在从不会将控制权返回给事件循环的线程调用singleShot。需要事件循环处理,以便QTimer 可以工作。
    【解决方案2】:

    QTimer::singleShot() 函数创建一个 QTimer 对象并在内部完成所有信号设置和清理工作。

    线程亲和性将与正在运行的执行该函数的线程相关。

    【讨论】:

    • 你错了,看我的回答。 QTimer 没有被创建,而是内部类QSingleShotTimer 的一些对象。
    猜你喜欢
    • 2017-12-06
    • 2011-01-15
    • 2012-11-07
    • 2013-04-25
    • 2019-08-09
    • 1970-01-01
    相关资源
    最近更新 更多