[Qt-interest] Best practices for a thread object

Andre Somers andre at familiesomers.nl
Sun Jan 16 17:14:05 CET 2011


Hi,

Op 16-1-2011 16:50, Etienne Sandré-Chardonnal schreef:
> Dear all,
>
> In my application, I define a "Worker" class, which inherits QThread. 
> This worker class lives its own life in its thread and does computations.
Fine, that can work.
> My main GUI application thread creates a myWorker instance of this 
> worker class and call Worker::run().
You can not do that. QThread::run is protected, so you can not call it 
from outside the thread object itself. You should can call QThread::start().
> This means, the myWorker instance belongs to the main app thread from 
> which it was created. Then, within Worker::run(), I cannot create 
> children QObjects, as this gives me the classical error message:
> QObject: Cannot create children for a parent that is in a different 
> thread.
Obviously. QThread is a class that *manages* a thread. It lives in 
whatever thread it was created in, usually the GUI/main thread. If you 
want to create new QObjects from QThread::run (which is called from the 
new thread's context, not from the thread the QThread object itself runs 
in), you can do so. They just can not have a parent object that is in 
another thread. That means that per thread, there is at least one 
QObject instance that does not have a parent object: it is at the top of 
a parent/child hierarchy. That means that you need to either create it 
on the stack (like you do in your main function with QApplication 
probably), or make sure you delete it yourself.
> I fully understand this error message. But what would be the best 
> practices for doing this?
>
> I'm thinking of using moveToThread for this, such as:
>
> MainApp::startComputation()
> {
>     myWorker = new Worker();
>     myWorker->moveToThread(myWorker);
>     myWorker->run();
> }
No. Don't move a QThread onto itself. It will probably not work the way 
you intended it to work! If you make Worker just inherit QObject, you 
can do this:

MainApp::startComputation()
{
     myWorker = new Worker();
     myWorkerThread = new QThread(this);
     myWorker->moveToThread(myWorkerThread );
     myWorkerThread ->start();
}

Note that QThread is used directly. No subclassing involved at all. We 
use the fact that QThread::run() by default just calls QThread::exec(). 
That is enough to use objects and have working signal-slot connections.

> Is it possible or stupid to move a QThread to itself with moveToThread?
Yes to both. Don't do that.
> Should I do this before or after calling run() ?
You should do neither: don't move a thread object to its own thread, and 
don't call run().
> What is the exact meaning of the belonging of a QObject to a QThread? 
> I do not see which mechanism is involved.
It has to do with event delivery and signal-slot connections between 
threads.

Take a look at this [1] article in the DevNet Wiki for a more in-depth 
explanation on how to work with QObjects and QThreads. Read it all. It 
starts with the "old-fashioned" method that involves re-implementing 
QThread::run(), but nowadays the recommended way of working is using 
QThread as-is, and moving your worker object to it.

[1] http://developer.qt.nokia.com/wiki/ThreadsEventsQObjects

André




More information about the Qt-interest-old mailing list