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 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?

    sierdzioS VRoninV 2 Replies Last reply
    0
    • C Crindu

      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?

      sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on 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
      5
      • C Crindu

        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?

        VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by VRonin
        #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
        • VRoninV VRonin

          @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 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?

          VRoninV 1 Reply Last reply
          0
          • sierdzioS sierdzio

            @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 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

              @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?

              VRoninV Offline
              VRoninV Offline
              VRonin
              wrote on 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
              0
              • VRoninV VRonin

                @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 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?

                VRoninV 1 Reply Last reply
                0
                • C Crindu

                  @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?

                  VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by VRonin
                  #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
                  4
                  • VRoninV VRonin

                    @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 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

                    • Login

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