How do QThread::start and Worker::doWork related?
-
@beecksche said in How do QThread::start and Worker::doWork related?:
The slot doWork of the Worker class is connected to the signal operate of the controller
connect(this, &Controller::operate, worker, &Worker::doWork);
Who emits the Controller::operate signal?
I've checked doc of QThread, but no answer.@jronald said in How do QThread::start and Worker::doWork related?:
Who emits the Controller::operate signal?
It's just an example. Who emits the signal is not of interest in this example. It just shows how you can connect the worker with the controller.
In a real application the controller would emit this signal whenever the action needs to be executed in the thread. -
@beecksche said in How do QThread::start and Worker::doWork related?:
The slot doWork of the Worker class is connected to the signal operate of the controller
connect(this, &Controller::operate, worker, &Worker::doWork);
Who emits the Controller::operate signal?
I've checked doc of QThread, but no answer.@jronald
the document does not say who emit theController::operate
signal.it just gives you a way to start
doWork
by emitController::operate
signal, as for where or when you want to emit the signal, it depends on how you define theController
for example, you can add a public member function in
Controller
doWork() { emit operate; }
then when you call
doWork
in your main function, it will startWorker::doWork
in another thread. -
From the doc of QThread:
class Worker : public QObject { Q_OBJECT public slots: void doWork(const QString ¶meter) { 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 &); };
Question:
How doworkerThread::start
and
Worker::doWork
related?
Thanks in advance.[Please don't delete your topics. Restored. ~kshegunov]
@jronald if you want to start the doWork slot immediately after starting the thread, you can link those two together
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); connect(&workerThread, &QThread::started, this, &Controller::operate); //<-- Added connection workerThread.start(); }
-
@jronald if you want to start the doWork slot immediately after starting the thread, you can link those two together
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); connect(&workerThread, &QThread::started, this, &Controller::operate); //<-- Added connection workerThread.start(); }
-
@J.Hilk OK. It seems that even a running thread could be moved from thread to thread, is it true?
-
@J.Hilk OK. It seems that even a running thread could be moved from thread to thread, is it true?
@jronald said in How do QThread::start and Worker::doWork related?:
@J.Hilk OK. It seems that even a running thread could be moved from thread to thread, is it true?
The QThread object itself just manages one thread. That said, it's not strictly necessary to move/asign your worker-object to the QThread-Object before it is started.
But if you create for example a QTimer in your worker and move it than later to an other QThread, that won't work. Iirc the Timer releated things are ignored/not executed.
That is also true if you create instances of classes that have internal time specific things.
For example I run into this, when I had an QSerialPort object that was created in the constructor, had to move it the an initialization function that was called after the QThread started. -
@jronald said in How do QThread::start and Worker::doWork related?:
@J.Hilk OK. It seems that even a running thread could be moved from thread to thread, is it true?
The QThread object itself just manages one thread. That said, it's not strictly necessary to move/asign your worker-object to the QThread-Object before it is started.
But if you create for example a QTimer in your worker and move it than later to an other QThread, that won't work. Iirc the Timer releated things are ignored/not executed.
That is also true if you create instances of classes that have internal time specific things.
For example I run into this, when I had an QSerialPort object that was created in the constructor, had to move it the an initialization function that was called after the QThread started.@J.Hilk said in How do QThread::start and Worker::doWork related?:
But if you create for example a QTimer in your worker and move it than later to an other QThread, that won't work. Iirc the Timer releated things are ignored/not executed.
The timer should be stopped before moving to another thread, you can't move an active timer.
-
@jronald said in How do QThread::start and Worker::doWork related?:
@J.Hilk OK. It seems that even a running thread could be moved from thread to thread, is it true?
The QThread object itself just manages one thread. That said, it's not strictly necessary to move/asign your worker-object to the QThread-Object before it is started.
But if you create for example a QTimer in your worker and move it than later to an other QThread, that won't work. Iirc the Timer releated things are ignored/not executed.
That is also true if you create instances of classes that have internal time specific things.
For example I run into this, when I had an QSerialPort object that was created in the constructor, had to move it the an initialization function that was called after the QThread started. -
@J.Hilk @VRonin @kshegunov
Not clear, I think I'll try the native API. Thanks.@jronald said in How do QThread::start and Worker::doWork related?:
Not clear
Try taking a look at https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
-
@J.Hilk @VRonin @kshegunov
Not clear, I think I'll try the native API. Thanks.@jronald said in How do QThread::start and Worker::doWork related?:
Not clear, I think I'll try the native API.
What isn't clear exactly?
-
@jronald said in How do QThread::start and Worker::doWork related?:
Not clear
Try taking a look at https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
-
@jronald said in How do QThread::start and Worker::doWork related?:
Not clear, I think I'll try the native API.
What isn't clear exactly?
@kshegunov said in How do QThread::start and Worker::doWork related?:
@jronald said in How do QThread::start and Worker::doWork related?:
Not clear, I think I'll try the native API.
What isn't clear exactly?
Some questions can't be answered, for example:
- what if many workers move to the same thread object
- worker and QThread object are decoupled, what is the mechanism to keep both valid when working? By something like share_ptr?
-
@kshegunov said in How do QThread::start and Worker::doWork related?:
@jronald said in How do QThread::start and Worker::doWork related?:
Not clear, I think I'll try the native API.
What isn't clear exactly?
Some questions can't be answered, for example:
- what if many workers move to the same thread object
- worker and QThread object are decoupled, what is the mechanism to keep both valid when working? By something like share_ptr?
@jronald
I hope i understand your questions correctly.By calling the QThread::start a new event loop is started. The objects moved to this QThread will be executed in that event loop. So if multiple objects are moved to the thread the operations are done in sequence.
To communicate between the objects moved to the thread and object in another thread you can use the signal/slot mechanism with queued connections.
Here a also useful informations: http://doc.qt.io/qt-5.8/threads-synchronizing.html and http://doc.qt.io/qt-5/threads-technologies.html
-
@jronald
I hope i understand your questions correctly.By calling the QThread::start a new event loop is started. The objects moved to this QThread will be executed in that event loop. So if multiple objects are moved to the thread the operations are done in sequence.
To communicate between the objects moved to the thread and object in another thread you can use the signal/slot mechanism with queued connections.
Here a also useful informations: http://doc.qt.io/qt-5.8/threads-synchronizing.html and http://doc.qt.io/qt-5/threads-technologies.html
@beecksche The mechanism is general and robust, the trade off between runtime efficiency and develop efficiency while retaining the profession of C/C++ is very good.
-
@kshegunov said in How do QThread::start and Worker::doWork related?:
@jronald said in How do QThread::start and Worker::doWork related?:
Not clear, I think I'll try the native API.
What isn't clear exactly?
Some questions can't be answered, for example:
- what if many workers move to the same thread object
- worker and QThread object are decoupled, what is the mechanism to keep both valid when working? By something like share_ptr?
@jronald said in How do QThread::start and Worker::doWork related?:
what if many workers move to the same thread object
The
QObject::moveToThread
method is not thread-safe. In consequence the object can be moved only from one thread and it is the one it exists in (see thread affinity). Aside from this there's no limit on how many worker objects can be moved into a thread. All the slot invocations across threads are queued (by default) in the thread's event queue and are dispatched to the relevant objects in sequence.worker and QThread object are decoupled, what is the mechanism to keep both valid when working? By something like share_ptr?
That's up to you. I just connect all the needed signals and don't keep reference to either object, or I create them in the stack and leave the stack unwinding to take care of the objects' destruction. E.g:
QThread * thread = new QThread(); thread->start(); QObject * worker = new QObject(); // Or whatever type your worker is. worker->moveToThread(thread); // Connect worker and thread and w/e else is needed to be connected QObject::connect(thread, &QThread::finished, worker, &QObject::deleteLater); // Takes care to delete the worker whenever the thread's quitting // Do unrelated stuff ... ... // Tell the thread to quit, wait for it and continue on thread->quit(); thread->wait();
As
QThread
is already aQObject
you can have it parented which means the parent will auto-delete the children whenever it is deleted itself. -
@jronald said in How do QThread::start and Worker::doWork related?:
what if many workers move to the same thread object
The
QObject::moveToThread
method is not thread-safe. In consequence the object can be moved only from one thread and it is the one it exists in (see thread affinity). Aside from this there's no limit on how many worker objects can be moved into a thread. All the slot invocations across threads are queued (by default) in the thread's event queue and are dispatched to the relevant objects in sequence.worker and QThread object are decoupled, what is the mechanism to keep both valid when working? By something like share_ptr?
That's up to you. I just connect all the needed signals and don't keep reference to either object, or I create them in the stack and leave the stack unwinding to take care of the objects' destruction. E.g:
QThread * thread = new QThread(); thread->start(); QObject * worker = new QObject(); // Or whatever type your worker is. worker->moveToThread(thread); // Connect worker and thread and w/e else is needed to be connected QObject::connect(thread, &QThread::finished, worker, &QObject::deleteLater); // Takes care to delete the worker whenever the thread's quitting // Do unrelated stuff ... ... // Tell the thread to quit, wait for it and continue on thread->quit(); thread->wait();
As
QThread
is already aQObject
you can have it parented which means the parent will auto-delete the children whenever it is deleted itself.@kshegunov The signal & slot mechanism just takes thread selection into consideration, others still keep simple, right? I think it's quite good.
-
@kshegunov The signal & slot mechanism just takes thread selection into consideration, others still keep simple, right? I think it's quite good.
I'm sorry, I don't understand the question.