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. MoveToThread and QTimer
QtWS25 Last Chance

MoveToThread and QTimer

Scheduled Pinned Locked Moved General and Desktop
movetothreadqthread
12 Posts 4 Posters 16.6k 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.
  • T Offline
    T Offline
    tlvju
    wrote on last edited by koahnig
    #1

    Hi,

    I cannot figure out how moveToThread is working with QTimer class member.

    I have a simple code example of my problem.

    Description of the code example:
    MyObject1:
    Create MyObject2.
    Move MyObject2 to a thread using moveToThread.
    Connect the started signal from QThread to the MyObject1 slot process.

    MyObject2:
    Class that inherits from QObject.
    Contain a QTimer member.
    Contain a process slot.

    Running behavior:
    In the process slot of MyObject2 I start my QTimer class member and I get:
    @QObject::startTimer: timers cannot be started from another thread@

    Resolve the problem:
    I can get rid of this, by defining my QTimer member as a pointer and create it in the process slot.

    Question:
    What I do not understand is why in the case that my QTimer class member is not a pointer, my timer is running in a different thread?
    moveToThread should make it running in the same thread as MyObject2 thread, no?

    Code example:
    @#include <QDebug>
    #include <QThread>

    #include "mythread1.h"
    #include "mythread2.h"

    MyObject1::MyObject1(QObject *parent) :
    QObject(parent)
    {
    qDebug() << "Constructor object1, THREAD :" << QThread::currentThreadId();

     m_object2 = new MyObject2();
     QThread *thread1 = new QThread();
     m_object2->moveToThread(thread1);
     connect (thread1, SIGNAL(started()), m_object2, SLOT(process()));
     thread1->start();
    

    }

    #ifndef MYTHREAD1_H
    #define MYTHREAD1_H

    #include "mythread2.h"

    class MyObject1 : public QObject
    {
    Q_OBJECT
    public:
    explicit MyObject1(QObject *parent = 0);

    MyObject2 *m_object2;
    

    signals:
    public slots:
    protected:
    private:
    };

    #endif // MYTHREAD1_H

    #include <QDebug>
    #include <QThread>
    #include "mythread2.h"

    MyObject2::MyObject2(QObject *parent) :
    QObject(parent)
    {
    qDebug() << "Constructor object2, THREAD :" << QThread::currentThreadId();
    }

    void MyObject2::process()
    {
    qDebug() << "Object2" << func << "THREAD :" << QThread::currentThreadId();
    m_timer.setInterval(5000);
    connect (&m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
    m_timer.start();
    }

    void MyObject2::onTimeout()
    {
    qDebug() << func << "Object2 THREAD :" << QThread::currentThreadId();
    }

    #ifndef MYTHREAD2_H
    #define MYTHREAD2_H

    #include <QTimer>

    class MyObject2 : public QObject
    {
    Q_OBJECT
    public:
    explicit MyObject2(QObject *parent = 0);

    QTimer m_timer;
    

    signals:

    public slots:
    void process(void);
    void onTimeout(void);

    protected:

    };

    #endif // MYTHREAD2_H@

    Thanks in advance for your help.

    Julien.

    1 Reply Last reply
    0
    • L Offline
      L Offline
      luca.cossaro
      wrote on last edited by
      #2

      Hi, I've not checked directly, but the timer is not a child of MyObject2 thus is not moved to the new thread.

      1 Reply Last reply
      0
      • P Offline
        P Offline
        pixlmakr
        wrote on last edited by
        #3

        [quote author="tlvju" date="1350384177"]
        moveToThread should make it running in the same thread as MyObject2 thread, no?
        [/quote]

        I have the same question. Why m_timer isn't moved to another thread?

        1 Reply Last reply
        0
        • L Offline
          L Offline
          luca.cossaro
          wrote on last edited by
          #4

          m_timer is not parented to anything, thus it is not moved to the thread.

          1 Reply Last reply
          0
          • L Offline
            L Offline
            lgeyer
            wrote on last edited by
            #5

            Be aware that just because m_timer is a member of a QObject-based class, it does not automatically become a child of it and thus, as luca already pointed out, it is not moved to the new thread.

            You either move it explicitly or set the surrouding class as the parent to get it moved implicitly.

            1 Reply Last reply
            0
            • P Offline
              P Offline
              pixlmakr
              wrote on last edited by
              #6

              Thanks luca, you've answered about our question above but I didn't read it. Sorry.

              I tried:

              1. Add new member variables to MyObject2 (QTimer* m_timer2, m_timer3).
              2. Add this code under line 55 (MyObject2::process()).
                @m_timer2 = new QTimer();
                m_timer3 = new QTimer(this);
                qDebug() << "Parent of m_timer is" << m_timer.parent();
                qDebug() << "Parent of m_timer2 is" << m_timer2->parent();
                qDebug() << "Parent of m_timer3 is" << m_timer3->parent();@

              Application output:
              @Constructor object1, THREAD : 3055531792
              Constructor object2, THREAD : 3055531792
              Object2 process THREAD : 3019897712
              Parent of m_timer is QObject(0x0)
              Parent of m_timer2 is QObject(0x0)
              Parent of m_timer3 is MyObject2(0x9563f20)
              ...@

              (Parent of m_timer and m_timer2 is QObject in my case)

              BANG! I got it.
              Thank you very much.

              Kay

              1 Reply Last reply
              0
              • P Offline
                P Offline
                pixlmakr
                wrote on last edited by
                #7

                Thank you Lukas!
                I 'm newbie and I didn't know that:
                [quote author="Lukas Geyer" date="1350451175"]m_timer is a member of a QObject-based class, it does not automatically become a child of it [/quote]

                Kay

                1 Reply Last reply
                0
                • T Offline
                  T Offline
                  tlvju
                  wrote on last edited by
                  #8

                  I understand now that my m_timer object class member is not a child of my object.

                  But I still do not understand something.
                  I have done what Kay tried, so having three timers created in three different ways and qDebug the parent of those timers.

                  You can see that m_timer2 has the same parent as m_timer but:
                  m_timer.start() is nok :
                  @QObject::startTimer: timers cannot be started from another thread@

                  m_timer2->start() is ok:
                  signal/slot are working

                  1 Reply Last reply
                  0
                  • L Offline
                    L Offline
                    lgeyer
                    wrote on last edited by
                    #9

                    Yes, m_timer and m_timer2 have the same parent, 0x0 or 0 or NULL or nullptr, which means that both have no parent. So m_timer is not moved to thread1.

                    1 Reply Last reply
                    0
                    • T Offline
                      T Offline
                      tlvju
                      wrote on last edited by
                      #10

                      bq. Yes, m_timer and m_timer2 have the same parent, 0×0, which means that both have no parent.

                      Then why m_timer2 is able to be started from the thread and m_timer not?
                      I expect that m_timer2 is also not able to be started.
                      Is it because a new is done in the function process so in the thread, and then m_timer2 is really living in the thread since created in it?

                      1 Reply Last reply
                      0
                      • L Offline
                        L Offline
                        lgeyer
                        wrote on last edited by
                        #11

                        Because m_timer2 has been created after m_object2 has been moved to thread1, whereas m_timer is created before. The code in process() is executed in thread1, not the main thread.

                        An object always 'lives' in the thread it has been created (until moved to another thread of course).

                        1 Reply Last reply
                        0
                        • T Offline
                          T Offline
                          tlvju
                          wrote on last edited by
                          #12

                          Ok great, thanks a lot for your answers, that's now completely clear :-).

                          1 Reply Last reply
                          0

                          • Login

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