Creating QThread from another QThread
-
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? -
@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).
-
@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 soreadThread,SIGNAL(finished())
will never fire and the object will not be deleted. same thing inQThread* thread = new QThread(QThread::currentThread()->parent());
as, in your example,QThread::currentThread()->parent()
is nullTBH, I think you are going overkill with this. As long as you can keep
buffer
alive until all the threads finish you can easily useQtConcurrent::run
to execute the two methods. Make sure there's no internal race condition betweenreadData
andsaveData
(the names would suggest there is so you'd need to manage it with mutexes/semaphores/read-write locks) -
@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?
-
@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 useQtConcurrent::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 destroyQThread
when the thread is running you will see a critical error in the debug output -
@VRonin
The second thread should start inside readData method, during the execution of the first thread.
If I useQtConcurrent::run(&buffer, &Buffer::readData);
, how can I retrieve the pointer to Buffer in order to create the second thread for saveData? -
@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 ofBuffer
so you can very easily usethis
:QtConcurrent::run(this, &Buffer::saveData);