Important: Please read the Qt Code of Conduct -

QThread correct usage (Qt 5.9)

  • Doing some test with QThread I found a basic issue that I'm unable to solve in an elegant way. What I did is to create a "worker thread" and move my class to this thread. In my main file I do:

    StateMachine *testStateMachine1 = new StateMachine(1500);
    TestThread *testThread1 = new TestThread();
    connect(testThread1, SIGNAL(started()), testStateMachine1, SLOT(process()));
    connect(testStateMachine1, SIGNAL(finished()), testThread1, SLOT(quit()));
    connect(testStateMachine1, SIGNAL(finished()), testStateMachine1, SLOT(deleteLater()));
    connect(testThread1, SIGNAL(finished()), testThread1, SLOT(deleteLater()));
    testThread1->start ();

    Here is my "worker thread" class:

    class TestThread : public QThread
            void run (void) { exec(); }  

    Here part of the class: StateMachine (the one moved in the thread):

    class StateMachine : public QObject
        void Exec(int pollingTimeMSec = 1000);
        virtual ~StateMachine ();
        void TestStateMachine::process() { Exec(1000); }
        QStateMachine *machine;
        QTimer timer;

    The Exec function is called from the process function that is called by the "worker" thread (all executed following guidelines from Qt documentation and forums).

    All is working but... the timer. It is not declared as a pointer (like QStateMachine) then timer still belongs to main thread and in the Exec() function I cannot do timer.start() because I get:
    QObject::startTimer: Timers cannot be started from another thread

    I cannot move it to the current thread either because it can be moved only by the thread of belonging.
    The only solution I can think of is to have a function to call from main thread to move the object but it is not so nice (think about having a lot of members to move).

    Am I doing something basically wrong or what?

  • Moderators

    @alsavi said in QThread correct usage (Qt 5.9):

        : QObject(nullptr), machine(nullptr), timer(this)

  • It works like a charm. I really did not think to break the object tree created by QObject.


  • Moderators

    You don't. You add the timer to the object tree rooted at the StateMachine object intentionally. The parent will move its children when it itself is moved to another thread. So your state machine object will move the timer to the correct thread. Additionally, as you don't seem to care to keep binary compatibility (which is fine in most cases), you could just create the QStateMachine on the stack the same way as the timer, it's faster and more robust.

Log in to reply