Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QThread correct usage (Qt 5.9)
Qt 6.11 is out! See what's new in the release blog

QThread correct usage (Qt 5.9)

Scheduled Pinned Locked Moved Unsolved General and Desktop
4 Posts 2 Posters 2.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    alsavi
    wrote on last edited by
    #1

    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();
    testStateMachine1->moveToThread(testThread1);
    
    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
    {
        Q_OBJECT
    
        public:
            TestThread();
    
            void run (void) { exec(); }  
    };
    

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

    class StateMachine : public QObject
    {
        Q_OBJECT
    
    public:
        StateMachine();
        void Exec(int pollingTimeMSec = 1000);
        virtual ~StateMachine ();
        void TestStateMachine::process() { Exec(1000); }
    }
    private:
        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?

    kshegunovK 1 Reply Last reply
    0
    • A alsavi

      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();
      testStateMachine1->moveToThread(testThread1);
      
      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
      {
          Q_OBJECT
      
          public:
              TestThread();
      
              void run (void) { exec(); }  
      };
      

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

      class StateMachine : public QObject
      {
          Q_OBJECT
      
      public:
          StateMachine();
          void Exec(int pollingTimeMSec = 1000);
          virtual ~StateMachine ();
          void TestStateMachine::process() { Exec(1000); }
      }
      private:
          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?

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by
      #2

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

      StateMachine::StateMachine()
          : QObject(nullptr), machine(nullptr), timer(this)
      {
      }
      

      Read and abide by the Qt Code of Conduct

      1 Reply Last reply
      1
      • A Offline
        A Offline
        alsavi
        wrote on last edited by
        #3

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

        Thanks

        kshegunovK 1 Reply Last reply
        0
        • A alsavi

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

          Thanks

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #4

          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.

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply
          1

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved