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. inherite from QThread, but donnot overrider virtual void run(), is this OK?

inherite from QThread, but donnot overrider virtual void run(), is this OK?

Scheduled Pinned Locked Moved Unsolved General and Desktop
33 Posts 5 Posters 4.1k Views
  • 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.
  • O Offline
    O Offline
    opengpu
    wrote on 17 Jun 2019, 08:50 last edited by opengpu
    #1

    inherite from QThread, but donnot overrider virtual void run(), is this OK?

    class MyThread : public QThread
    {
    public:
        MyThread(QObject* parent) : QThread(parent) {}
        ~MyThread() { exit(); }
    protected:
        //virtual void run();//use the dafault QThread::run().
    protected slots:
        void slot_SendEmail(const MyInfo& info) {......;}
    }
    
    void main()
    {
        MyThread t;
        connect(...,...,...,slot_SendEmail);
         t.start();
        //and then emit the signal_SendEmail(const MyInfo& /*info*/) @MainThread in some class::function frequently
    }
    
    K 1 Reply Last reply 17 Jun 2019, 09:21
    0
    • O Offline
      O Offline
      opengpu
      wrote on 17 Jun 2019, 08:56 last edited by
      #2

      is the above code OK?
      or i have to maintain a vector/list of myInfo, and append into it @slot. while loop this vector/list @run()?

      K 1 Reply Last reply 17 Jun 2019, 09:05
      0
      • S Offline
        S Offline
        sierdzio
        Moderators
        wrote on 17 Jun 2019, 08:59 last edited by
        #3

        A more classic approach would be to use worker object here. But yes, what you wrote should work fine as long as you don't call slot_SendEmail() directly (to make sure your compiler will check this - move it to private part of your header).

        To be 100% sure you can print thread ID in main.cpp and in your slot - if they are different then the method is invoked in the thread.

        (Z(:^

        O 1 Reply Last reply 17 Jun 2019, 09:16
        2
        • O opengpu
          17 Jun 2019, 08:56

          is the above code OK?
          or i have to maintain a vector/list of myInfo, and append into it @slot. while loop this vector/list @run()?

          K Offline
          K Offline
          kshegunov
          Moderators
          wrote on 17 Jun 2019, 09:05 last edited by
          #4

          @opengpu said in inherite from QThread, but donnot overrider virtual void run(), is this OK?:

          is the above code OK?

          Not if you intend slot_SendEmail to be called in the thread you spawned, no. QThread is living in the main thread (as it should be). Use the worker object approach which @sierdzio alluded to.

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply
          4
          • S sierdzio
            17 Jun 2019, 08:59

            A more classic approach would be to use worker object here. But yes, what you wrote should work fine as long as you don't call slot_SendEmail() directly (to make sure your compiler will check this - move it to private part of your header).

            To be 100% sure you can print thread ID in main.cpp and in your slot - if they are different then the method is invoked in the thread.

            O Offline
            O Offline
            opengpu
            wrote on 17 Jun 2019, 09:16 last edited by
            #5

            @sierdzio said in inherite from QThread, but donnot overrider virtual void run(), is this OK?:

            use worker object here

            how to use worker object here? is there any doc or demo?

            1 Reply Last reply
            0
            • O Offline
              O Offline
              opengpu
              wrote on 17 Jun 2019, 09:18 last edited by
              #6

              the slot_SendEmail is slow, and the emit signal_SendEmail is very very frequently.
              so is it OK when the previous signal's slot_SendEmail is still not finished & the next (maybe more than one)signal_SendEmail is already emitted.

              1 Reply Last reply
              0
              • O opengpu
                17 Jun 2019, 08:50

                inherite from QThread, but donnot overrider virtual void run(), is this OK?

                class MyThread : public QThread
                {
                public:
                    MyThread(QObject* parent) : QThread(parent) {}
                    ~MyThread() { exit(); }
                protected:
                    //virtual void run();//use the dafault QThread::run().
                protected slots:
                    void slot_SendEmail(const MyInfo& info) {......;}
                }
                
                void main()
                {
                    MyThread t;
                    connect(...,...,...,slot_SendEmail);
                     t.start();
                    //and then emit the signal_SendEmail(const MyInfo& /*info*/) @MainThread in some class::function frequently
                }
                
                K Offline
                K Offline
                KroMignon
                wrote on 17 Jun 2019, 09:21 last edited by
                #7

                @opengpu I don't think this is OK. There is a common mistake with QThread usage.
                QThread is a Qt object which will control a thread, but QThread instance leaves in the thread in which the instance has been created, not in the created thread.
                So the slots/signals of the MyThread class will be launched in the thread used to create the MyThread instance.

                A good practice for multi-threading with Qt, is to create a worker class and to move the instance to the thread, not to sub-class QThread.

                Take a look at following links for more details:

                • http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
                • http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-2/
                • https://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/
                • https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

                It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                O S 2 Replies Last reply 17 Jun 2019, 09:30
                1
                • K KroMignon
                  17 Jun 2019, 09:21

                  @opengpu I don't think this is OK. There is a common mistake with QThread usage.
                  QThread is a Qt object which will control a thread, but QThread instance leaves in the thread in which the instance has been created, not in the created thread.
                  So the slots/signals of the MyThread class will be launched in the thread used to create the MyThread instance.

                  A good practice for multi-threading with Qt, is to create a worker class and to move the instance to the thread, not to sub-class QThread.

                  Take a look at following links for more details:

                  • http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
                  • http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-2/
                  • https://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/
                  • https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
                  O Offline
                  O Offline
                  opengpu
                  wrote on 17 Jun 2019, 09:30 last edited by opengpu
                  #8

                  @KroMignon thank you , i think you are right. the signal and slot will be both at MainThread...before this i normally overide the virutal run(), and mainly do things @run().
                  at this time, i just need to SendMail(const MyInfo& info), so i tried to make it simple, without loop @run() with a list.

                  1 Reply Last reply
                  0
                  • K KroMignon
                    17 Jun 2019, 09:21

                    @opengpu I don't think this is OK. There is a common mistake with QThread usage.
                    QThread is a Qt object which will control a thread, but QThread instance leaves in the thread in which the instance has been created, not in the created thread.
                    So the slots/signals of the MyThread class will be launched in the thread used to create the MyThread instance.

                    A good practice for multi-threading with Qt, is to create a worker class and to move the instance to the thread, not to sub-class QThread.

                    Take a look at following links for more details:

                    • http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
                    • http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-2/
                    • https://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/
                    • https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
                    S Offline
                    S Offline
                    sierdzio
                    Moderators
                    wrote on 17 Jun 2019, 09:37 last edited by
                    #9

                    @KroMignon said in inherite from QThread, but donnot overrider virtual void run(), is this OK?:

                    So the slots/signals of the MyThread class will be launched in the thread used to create the MyThread instance.

                    Yep, I've just tested. @opengpu so you have to use worker object or implement run(). Both approaches are described in great detail in QThread documentation.

                    (Z(:^

                    1 Reply Last reply
                    1
                    • O Offline
                      O Offline
                      opengpu
                      wrote on 17 Jun 2019, 09:56 last edited by opengpu
                      #10
                      class Worker : public QObject
                      {
                          Q_OBJECT
                      
                      public slots:
                          void doWork(const QString &parameter) {
                              QString result;
                              /* ... here is the expensive or blocking operation ... */
                              emit resultReady(result);
                          }
                      
                      signals:
                          void resultReady(const QString &result);
                      };
                      
                      class Controller : public QObject
                      {
                          Q_OBJECT
                          QThread workerThread;
                      public:
                          Controller() {
                              Worker *worker = new Worker;
                              worker->moveToThread(&workerThread);
                              connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
                              connect(this, &Controller::operate, worker, &Worker::doWork);
                              connect(worker, &Worker::resultReady, this, &Controller::handleResults);
                              workerThread.start();
                          }
                          ~Controller() {
                              workerThread.quit();
                              workerThread.wait();
                          }
                      public slots:
                          void handleResults(const QString &);
                      signals:
                          void operate(const QString &);
                      };
                      

                      thanks, and i will use this.

                      ///////////////////////////////////////////////////////////////////////////////////////////////
                      is this OK?
                      the 'doWork' is slow, and the emit 'operate' is very very frequently.
                      so is it OK when the previous signal's 'doWork' is still not finished & the next (maybe more than one)'operate' is already emitted.

                      K 1 Reply Last reply 17 Jun 2019, 12:32
                      0
                      • O opengpu
                        17 Jun 2019, 09:56
                        class Worker : public QObject
                        {
                            Q_OBJECT
                        
                        public slots:
                            void doWork(const QString &parameter) {
                                QString result;
                                /* ... here is the expensive or blocking operation ... */
                                emit resultReady(result);
                            }
                        
                        signals:
                            void resultReady(const QString &result);
                        };
                        
                        class Controller : public QObject
                        {
                            Q_OBJECT
                            QThread workerThread;
                        public:
                            Controller() {
                                Worker *worker = new Worker;
                                worker->moveToThread(&workerThread);
                                connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
                                connect(this, &Controller::operate, worker, &Worker::doWork);
                                connect(worker, &Worker::resultReady, this, &Controller::handleResults);
                                workerThread.start();
                            }
                            ~Controller() {
                                workerThread.quit();
                                workerThread.wait();
                            }
                        public slots:
                            void handleResults(const QString &);
                        signals:
                            void operate(const QString &);
                        };
                        

                        thanks, and i will use this.

                        ///////////////////////////////////////////////////////////////////////////////////////////////
                        is this OK?
                        the 'doWork' is slow, and the emit 'operate' is very very frequently.
                        so is it OK when the previous signal's 'doWork' is still not finished & the next (maybe more than one)'operate' is already emitted.

                        K Offline
                        K Offline
                        KroMignon
                        wrote on 17 Jun 2019, 12:32 last edited by KroMignon
                        #11

                        @opengpu said in inherite from QThread, but donnot overrider virtual void run(), is this OK?:

                        so is it OK when the previous signal's 'doWork' is still not finished & the next (maybe more than one)'operate' is already emitted.

                        The worker QThread implements a QEventQueue, when a new signal emitted from Controller, it will be stored in message queue. And when slot has been processed on Worker, next message will be extract from queue. And so on.

                        More details can be found here: https://www.toptal.com/qt/qt-multithreading-c-plus-plus

                        Messages will be processed in the order of reception in WorkerThread.

                        I would to initialization of Thread and Worker like this:

                        Worker *worker = new Worker; // no need to hold pointer to worker 
                        QThread *workerThread = new QThread; // no need to hold pointer to worker thread
                        
                        connect(this, &Controller::operate, worker, Worker::doWork);
                        connect(worker, &Worker::resultReady, this, &Controller::handleResults);
                        
                        // delete worker on controller end
                        connect(this, &QObject::destroyed, worker, Worker::deleteLater, Qt::DirectConnection);
                        
                        // stop and delete worker thread on worker end
                        connect(worker, &QObject::destroyed, workerThread, [](QObject *){
                            quit();
                            wait();
                            deleteLater();
                        }, Qt::DirectConnection);
                        
                        worker->moveToThread(workerThread);
                        workerThread.start();
                        

                        It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                        K 1 Reply Last reply 17 Jun 2019, 19:27
                        1
                        • K KroMignon
                          17 Jun 2019, 12:32

                          @opengpu said in inherite from QThread, but donnot overrider virtual void run(), is this OK?:

                          so is it OK when the previous signal's 'doWork' is still not finished & the next (maybe more than one)'operate' is already emitted.

                          The worker QThread implements a QEventQueue, when a new signal emitted from Controller, it will be stored in message queue. And when slot has been processed on Worker, next message will be extract from queue. And so on.

                          More details can be found here: https://www.toptal.com/qt/qt-multithreading-c-plus-plus

                          Messages will be processed in the order of reception in WorkerThread.

                          I would to initialization of Thread and Worker like this:

                          Worker *worker = new Worker; // no need to hold pointer to worker 
                          QThread *workerThread = new QThread; // no need to hold pointer to worker thread
                          
                          connect(this, &Controller::operate, worker, Worker::doWork);
                          connect(worker, &Worker::resultReady, this, &Controller::handleResults);
                          
                          // delete worker on controller end
                          connect(this, &QObject::destroyed, worker, Worker::deleteLater, Qt::DirectConnection);
                          
                          // stop and delete worker thread on worker end
                          connect(worker, &QObject::destroyed, workerThread, [](QObject *){
                              quit();
                              wait();
                              deleteLater();
                          }, Qt::DirectConnection);
                          
                          worker->moveToThread(workerThread);
                          workerThread.start();
                          
                          K Offline
                          K Offline
                          kshegunov
                          Moderators
                          wrote on 17 Jun 2019, 19:27 last edited by
                          #12

                          @KroMignon said in inherite from QThread, but donnot overrider virtual void run(), is this OK?:

                          connect(this, &QObject::destroyed, worker, Worker::deleteLater, Qt::DirectConnection);
                          

                          This is a race condition - deleteLater is a slot and it's not thread-safe. Don't force the connection type.

                          Read and abide by the Qt Code of Conduct

                          K 1 Reply Last reply 18 Jun 2019, 07:04
                          4
                          • O Offline
                            O Offline
                            opengpu
                            wrote on 17 Jun 2019, 20:26 last edited by opengpu
                            #13

                            i want to set a min time interval inside which the emit operate or the slot doWork should be INVALID and do nothing.
                            before when overrider the virtual run(), that's easy to do.

                            how about this situation while using this worker-method?

                            eg. if doWork is implemented and until 1 min passed, the signal or slot should not emit or implemented in this 1 min. and the signal/slot doesnot be renmembered, just ignore them.

                            K 1 Reply Last reply 17 Jun 2019, 20:34
                            0
                            • O opengpu
                              17 Jun 2019, 20:26

                              i want to set a min time interval inside which the emit operate or the slot doWork should be INVALID and do nothing.
                              before when overrider the virtual run(), that's easy to do.

                              how about this situation while using this worker-method?

                              eg. if doWork is implemented and until 1 min passed, the signal or slot should not emit or implemented in this 1 min. and the signal/slot doesnot be renmembered, just ignore them.

                              K Offline
                              K Offline
                              kshegunov
                              Moderators
                              wrote on 17 Jun 2019, 20:34 last edited by
                              #14

                              Emit a deadline (QDeadlineTimer) along with the input data. In the slot check if the deadline has expired, and if so just return immediately.

                              Read and abide by the Qt Code of Conduct

                              1 Reply Last reply
                              0
                              • O Offline
                                O Offline
                                opengpu
                                wrote on 18 Jun 2019, 03:44 last edited by opengpu
                                #15
                                QElapsedTimer m_ElapsedTimer;
                                
                                if ( !m_ElapsedTimer.isValid() ||  m_ElapsedTimer.hasExpired(timeout))
                                {
                                    emit signalSendEmail();
                                    m_ElapsedTimer.restart();
                                }
                                

                                i want to write like this, this will not restrict the 1st time emit, and since the 1st emit, the next emit is only allowed outof timeout milliseconds.
                                However, i want the exe runs very very long time. the qinit64 seems still not that long enough for the longest interval in theory(qint64 is only about 214783 seconds). What will happen if the real time interval is longer than this?
                                And what is the best method to get the longest time interval supportted in code?

                                jsulmJ K 2 Replies Last reply 18 Jun 2019, 04:24
                                0
                                • O opengpu
                                  18 Jun 2019, 03:44
                                  QElapsedTimer m_ElapsedTimer;
                                  
                                  if ( !m_ElapsedTimer.isValid() ||  m_ElapsedTimer.hasExpired(timeout))
                                  {
                                      emit signalSendEmail();
                                      m_ElapsedTimer.restart();
                                  }
                                  

                                  i want to write like this, this will not restrict the 1st time emit, and since the 1st emit, the next emit is only allowed outof timeout milliseconds.
                                  However, i want the exe runs very very long time. the qinit64 seems still not that long enough for the longest interval in theory(qint64 is only about 214783 seconds). What will happen if the real time interval is longer than this?
                                  And what is the best method to get the longest time interval supportted in code?

                                  jsulmJ Offline
                                  jsulmJ Offline
                                  jsulm
                                  Lifetime Qt Champion
                                  wrote on 18 Jun 2019, 04:24 last edited by jsulm
                                  #16

                                  @opengpu See my answer in your other thread (https://forum.qt.io/topic/104026/about-the-longest-elapsed-time-in-qt). I really have no idea why you think it is 214783 seconds only when using qint64...

                                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                                  O 1 Reply Last reply 18 Jun 2019, 06:29
                                  0
                                  • jsulmJ jsulm
                                    18 Jun 2019, 04:24

                                    @opengpu See my answer in your other thread (https://forum.qt.io/topic/104026/about-the-longest-elapsed-time-in-qt). I really have no idea why you think it is 214783 seconds only when using qint64...

                                    O Offline
                                    O Offline
                                    opengpu
                                    wrote on 18 Jun 2019, 06:29 last edited by
                                    #17

                                    @jsulm thank you. i got it from INT_MAX, which is int32

                                    jsulmJ 1 Reply Last reply 18 Jun 2019, 06:34
                                    0
                                    • O opengpu
                                      18 Jun 2019, 06:29

                                      @jsulm thank you. i got it from INT_MAX, which is int32

                                      jsulmJ Offline
                                      jsulmJ Offline
                                      jsulm
                                      Lifetime Qt Champion
                                      wrote on 18 Jun 2019, 06:34 last edited by jsulm
                                      #18

                                      @opengpu With int32 you have more than 2 million seconds, not 214783

                                      https://forum.qt.io/topic/113070/qt-code-of-conduct

                                      1 Reply Last reply
                                      0
                                      • O Offline
                                        O Offline
                                        opengpu
                                        wrote on 18 Jun 2019, 06:44 last edited by
                                        #19

                                        @opengpu said in inherite from QThread, but donnot overrider virtual void run(), is this OK?:

                                        workerThread

                                        workerThread donot need sleep?

                                        jsulmJ 1 Reply Last reply 18 Jun 2019, 06:48
                                        0
                                        • O opengpu
                                          18 Jun 2019, 06:44

                                          @opengpu said in inherite from QThread, but donnot overrider virtual void run(), is this OK?:

                                          workerThread

                                          workerThread donot need sleep?

                                          jsulmJ Offline
                                          jsulmJ Offline
                                          jsulm
                                          Lifetime Qt Champion
                                          wrote on 18 Jun 2019, 06:48 last edited by
                                          #20

                                          @opengpu said in inherite from QThread, but donnot overrider virtual void run(), is this OK?:

                                          workerThread donot need sleep?

                                          No, they are not humans :-)
                                          Why are you asking? A thread can sleep or be busy.

                                          https://forum.qt.io/topic/113070/qt-code-of-conduct

                                          O 1 Reply Last reply 18 Jun 2019, 07:02
                                          1

                                          10/33

                                          17 Jun 2019, 09:56

                                          topic:navigator.unread, 23
                                          • Login

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