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. Creating QThread from another QThread
QtWS25 Last Chance

Creating QThread from another QThread

Scheduled Pinned Locked Moved Solved General and Desktop
qthreadmovetothread
9 Posts 3 Posters 3.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.
  • C Offline
    C Offline
    Crindu
    wrote on 6 Mar 2019, 18:27 last edited by
    #1

    I'm creating an application that perform a long task and after condition should spawn a second thread to do some computation.

    class Buffer : public QObject
    {
        Q_OBJECT
    public:
        Buffer(QObject* parent = 0);
    private:
        
    public slots:
        void readData();
        void saveData();
    
    };
    

    The readData method has an infinity loop inside and so I decided to move the Buffer object to a Qthread in the main.

    Buffer buffer;
    QThread *readThread = new QThread;
    readThread->setObjectName("customThread");
    readThread->setParent(&buffer);
    buffer.moveToThread(readThread);
    QObject::connect(readThread,SIGNAL(started()),&buffer,SLOT(readData()));
    QObject::connect(readThread,SIGNAL(finished()),thread,SLOT(deleteLater()));
    readThread->start();
    

    On some condition, checked in readData() method, I should call saveData() in another thread because the computation must be done concurrently with readData(). I tried this:

    
    QThread* thread = new QThread(QThread::currentThread()->parent());
    moveToThread(thread);
    connect(thread,SIGNAL(started()),QThread::currentThread()->parent(),SLOT(saveData()));
    connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()));
    thread->start();
    

    The first time that condition occurs, everything works fine. The second one, I get:

    QObject::moveToThread: Current thread (0xd29078) is not the object's thread (0x6e000df0).
    Cannot move to target thread (0x6e002c68)
    

    Probably because I change the affinity of readThread and I cannot call moveToThread again.
    Is there a way to solve this problem? Or is there a particular pattern that I should implement for this case?

    S V 2 Replies Last reply 6 Mar 2019, 19:11
    0
    • C Crindu
      6 Mar 2019, 18:27

      I'm creating an application that perform a long task and after condition should spawn a second thread to do some computation.

      class Buffer : public QObject
      {
          Q_OBJECT
      public:
          Buffer(QObject* parent = 0);
      private:
          
      public slots:
          void readData();
          void saveData();
      
      };
      

      The readData method has an infinity loop inside and so I decided to move the Buffer object to a Qthread in the main.

      Buffer buffer;
      QThread *readThread = new QThread;
      readThread->setObjectName("customThread");
      readThread->setParent(&buffer);
      buffer.moveToThread(readThread);
      QObject::connect(readThread,SIGNAL(started()),&buffer,SLOT(readData()));
      QObject::connect(readThread,SIGNAL(finished()),thread,SLOT(deleteLater()));
      readThread->start();
      

      On some condition, checked in readData() method, I should call saveData() in another thread because the computation must be done concurrently with readData(). I tried this:

      
      QThread* thread = new QThread(QThread::currentThread()->parent());
      moveToThread(thread);
      connect(thread,SIGNAL(started()),QThread::currentThread()->parent(),SLOT(saveData()));
      connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()));
      thread->start();
      

      The first time that condition occurs, everything works fine. The second one, I get:

      QObject::moveToThread: Current thread (0xd29078) is not the object's thread (0x6e000df0).
      Cannot move to target thread (0x6e002c68)
      

      Probably because I change the affinity of readThread and I cannot call moveToThread again.
      Is there a way to solve this problem? Or is there a particular pattern that I should implement for this case?

      S Offline
      S Offline
      sierdzio
      Moderators
      wrote on 6 Mar 2019, 19:11 last edited by
      #2

      @Crindu said in Creating QThread from another QThread:

      Probably because I change the affinity of readThread and I cannot call moveToThread again.
      Is there a way to solve this problem? Or is there a particular pattern that I should implement for this case?

      Move the creation of the new thread back to parent of your buffer thread. Should work, although it will introduce a small delay (buffer thread will need to send info to it's parent via signal, and then parent thread will start creating the new thread).

      (Z(:^

      C 1 Reply Last reply 6 Mar 2019, 21:31
      5
      • C Crindu
        6 Mar 2019, 18:27

        I'm creating an application that perform a long task and after condition should spawn a second thread to do some computation.

        class Buffer : public QObject
        {
            Q_OBJECT
        public:
            Buffer(QObject* parent = 0);
        private:
            
        public slots:
            void readData();
            void saveData();
        
        };
        

        The readData method has an infinity loop inside and so I decided to move the Buffer object to a Qthread in the main.

        Buffer buffer;
        QThread *readThread = new QThread;
        readThread->setObjectName("customThread");
        readThread->setParent(&buffer);
        buffer.moveToThread(readThread);
        QObject::connect(readThread,SIGNAL(started()),&buffer,SLOT(readData()));
        QObject::connect(readThread,SIGNAL(finished()),thread,SLOT(deleteLater()));
        readThread->start();
        

        On some condition, checked in readData() method, I should call saveData() in another thread because the computation must be done concurrently with readData(). I tried this:

        
        QThread* thread = new QThread(QThread::currentThread()->parent());
        moveToThread(thread);
        connect(thread,SIGNAL(started()),QThread::currentThread()->parent(),SLOT(saveData()));
        connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()));
        thread->start();
        

        The first time that condition occurs, everything works fine. The second one, I get:

        QObject::moveToThread: Current thread (0xd29078) is not the object's thread (0x6e000df0).
        Cannot move to target thread (0x6e002c68)
        

        Probably because I change the affinity of readThread and I cannot call moveToThread again.
        Is there a way to solve this problem? Or is there a particular pattern that I should implement for this case?

        V Offline
        V Offline
        VRonin
        wrote on 6 Mar 2019, 19:13 last edited by VRonin 3 Jun 2019, 19:15
        #3

        @Crindu said in Creating QThread from another QThread:

        Buffer buffer;

        Lifecycle is a race condition. If you create buffer on the stack, when the main thread will unwind that stack it will deallocate the memory of the object while another thread is working on it = race condition.

        QThread *readThread = new QThread; memory leak. you never stop the thread so readThread,SIGNAL(finished()) will never fire and the object will not be deleted. same thing in QThread* thread = new QThread(QThread::currentThread()->parent()); as, in your example, QThread::currentThread()->parent() is null

        TBH, I think you are going overkill with this. As long as you can keep buffer alive until all the threads finish you can easily use QtConcurrent::run to execute the two methods. Make sure there's no internal race condition between readData and saveData (the names would suggest there is so you'd need to manage it with mutexes/semaphores/read-write locks)

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        C 1 Reply Last reply 6 Mar 2019, 21:27
        6
        • V VRonin
          6 Mar 2019, 19:13

          @Crindu said in Creating QThread from another QThread:

          Buffer buffer;

          Lifecycle is a race condition. If you create buffer on the stack, when the main thread will unwind that stack it will deallocate the memory of the object while another thread is working on it = race condition.

          QThread *readThread = new QThread; memory leak. you never stop the thread so readThread,SIGNAL(finished()) will never fire and the object will not be deleted. same thing in QThread* thread = new QThread(QThread::currentThread()->parent()); as, in your example, QThread::currentThread()->parent() is null

          TBH, I think you are going overkill with this. As long as you can keep buffer alive until all the threads finish you can easily use QtConcurrent::run to execute the two methods. Make sure there's no internal race condition between readData and saveData (the names would suggest there is so you'd need to manage it with mutexes/semaphores/read-write locks)

          C Offline
          C Offline
          Crindu
          wrote on 6 Mar 2019, 21:27 last edited by
          #4

          @VRonin readThread has buffer as his parent:

          readThread->setParent(&buffer);
          

          Am I wrong?
          Yes the two methods have a lot of synchronization, I already managed it.
          Finally I tried this and seems to work.

          Buffer* buffer = (Buffer*)(QThread::currentThread()->parent());
          QtConcurrent::run(buffer, &Buffer::saveData);
          

          Do you think I should allocate Buffer on the heap, instead?

          V 1 Reply Last reply 7 Mar 2019, 08:25
          0
          • S sierdzio
            6 Mar 2019, 19:11

            @Crindu said in Creating QThread from another QThread:

            Probably because I change the affinity of readThread and I cannot call moveToThread again.
            Is there a way to solve this problem? Or is there a particular pattern that I should implement for this case?

            Move the creation of the new thread back to parent of your buffer thread. Should work, although it will introduce a small delay (buffer thread will need to send info to it's parent via signal, and then parent thread will start creating the new thread).

            C Offline
            C Offline
            Crindu
            wrote on 6 Mar 2019, 21:31 last edited by
            #5

            @sierdzio I already tried, it's strange because saveData is called but the error remains.

            1 Reply Last reply
            0
            • C Crindu
              6 Mar 2019, 21:27

              @VRonin readThread has buffer as his parent:

              readThread->setParent(&buffer);
              

              Am I wrong?
              Yes the two methods have a lot of synchronization, I already managed it.
              Finally I tried this and seems to work.

              Buffer* buffer = (Buffer*)(QThread::currentThread()->parent());
              QtConcurrent::run(buffer, &Buffer::saveData);
              

              Do you think I should allocate Buffer on the heap, instead?

              V Offline
              V Offline
              VRonin
              wrote on 7 Mar 2019, 08:25 last edited by
              #6

              @Crindu said in Creating QThread from another QThread:

              Finally I tried this and seems to work.

              You don't need QThread at all, you can just use QtConcurrent::run(&buffer, &Buffer::readData);.

              @Crindu said in Creating QThread from another QThread:

              readThread has buffer as his parent:
              readThread->setParent(&buffer);

              Am I wrong?

              Yes, QThread is not the thread, it's a wrapper around it, if you destroy QThread when the thread is running you will see a critical error in the debug output

              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
              ~Napoleon Bonaparte

              On a crusade to banish setIndexWidget() from the holy land of Qt

              C 1 Reply Last reply 7 Mar 2019, 10:41
              0
              • V VRonin
                7 Mar 2019, 08:25

                @Crindu said in Creating QThread from another QThread:

                Finally I tried this and seems to work.

                You don't need QThread at all, you can just use QtConcurrent::run(&buffer, &Buffer::readData);.

                @Crindu said in Creating QThread from another QThread:

                readThread has buffer as his parent:
                readThread->setParent(&buffer);

                Am I wrong?

                Yes, QThread is not the thread, it's a wrapper around it, if you destroy QThread when the thread is running you will see a critical error in the debug output

                C Offline
                C Offline
                Crindu
                wrote on 7 Mar 2019, 10:41 last edited by
                #7

                @VRonin
                The second thread should start inside readData method, during the execution of the first thread.
                If I use QtConcurrent::run(&buffer, &Buffer::readData); , how can I retrieve the pointer to Buffer in order to create the second thread for saveData?

                V 1 Reply Last reply 7 Mar 2019, 11:08
                0
                • C Crindu
                  7 Mar 2019, 10:41

                  @VRonin
                  The second thread should start inside readData method, during the execution of the first thread.
                  If I use QtConcurrent::run(&buffer, &Buffer::readData); , how can I retrieve the pointer to Buffer in order to create the second thread for saveData?

                  V Offline
                  V Offline
                  VRonin
                  wrote on 7 Mar 2019, 11:08 last edited by VRonin 3 Jul 2019, 11:20
                  #8

                  @Crindu said in Creating QThread from another QThread:

                  If I use QtConcurrent::run(&buffer, &Buffer::readData); , how can I retrieve the pointer to Buffer in order to create the second thread for saveData?

                  readData is a method of Buffer so you can very easily use this: QtConcurrent::run(this, &Buffer::saveData);

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  C 1 Reply Last reply 13 Mar 2019, 07:11
                  4
                  • V VRonin
                    7 Mar 2019, 11:08

                    @Crindu said in Creating QThread from another QThread:

                    If I use QtConcurrent::run(&buffer, &Buffer::readData); , how can I retrieve the pointer to Buffer in order to create the second thread for saveData?

                    readData is a method of Buffer so you can very easily use this: QtConcurrent::run(this, &Buffer::saveData);

                    C Offline
                    C Offline
                    Crindu
                    wrote on 13 Mar 2019, 07:11 last edited by
                    #9

                    @VRonin
                    Thank you, it works perfectly. I thought that ‘this’ could not be called inside a thread.

                    1 Reply Last reply
                    0

                    8/9

                    7 Mar 2019, 11:08

                    • Login

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