[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