[Qt-interest] Best practices for a thread object

K. Frank kfrank29.c at gmail.com
Sun Jan 16 18:50:08 CET 2011


Hello Etienne!

Please let me give you an iconoclastic defense of the
"moveToThread" approach you describe.

As Sean mentioned, this question does come up frequently,
as you can see in the archives.  For a recent discussion
provoked by my trouble-making, see:

   http://lists.qt.nokia.com/pipermail/qt-interest/2011-January/030205.html

2011/1/16 Etienne Sandré-Chardonnal <etienne.sandre at polytechnique.org>:
> 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.
>
> My main GUI application thread creates a myWorker instance of this worker
> class and call Worker::run().

(As Andre pointed out, you should call myWorker->start(),
rather than myWorker->run().)

> 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.
>
> 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:

I believe that this works just fine, and is a fully legitimate
approach.  (Having said that, the approach that I believe
Andre and Sean are advocating -- use a worker class derived
from QObject to do the work, and use QThread (or a class
derived from QThread) to manage the thread -- is also perfectly
fine, and is stylistically a little more object-oriented.)

>
> MainApp::startComputation()
> {
>     myWorker = new Worker();
>     myWorker->moveToThread(myWorker);

Yes.  Or -- my preference -- put "moveToThread (this)"
in Worker's constructor.

>     myWorker->run();

(Should be myWorker->start().)


> }
>
> Is it possible or stupid to move a QThread to itself with moveToThread?

It is possible, and not stupid.

> Should I do this before or after calling run() ?

You should call moveToThread before calling start() (which
calls the protected function run() under the hood).

>
> What is the exact meaning of the belonging of a QObject to a QThread? I do
> not see which mechanism is involved.

As Sean said, a QObject's thread affinity, i.e., to which
QThread it "belongs," is used to determine whether slots are
called synchronously (through a "direct" signal-slot connection),
or asynchronously (though a "queued" connection).

My take on the design trade-off between having a separate
QThread object and a QObject-derived worker object, vs.
deriving your worker object from QThread, and calling
"moveToThread (this)" is as follows:

For smaller projects where the business logic in your worker
object is less likely to be reused, the "moveToThread (this)"
approach can be a little more economical.  On the other hand,
the more object-oriented approach -- where you achieve greater
"separation of concerns" by having QThread manage the thread,
and your QObject-derived worker object deal with the business
logic -- can be beneficial in larger projects where you reuse the
worker object's business logic in other contexts, or you mix
multiple approaches to threading, such as individual worker
threads vs. thread pools.

Reasonable people can disagree as to the best approach.

What I disagree with is the assertion that "moveToThread"
is "wrong" or technically incorrect, or to statements such as
Andre's that "[moving] a QThread onto itself ... will probably
not work the way you intended it to work! "  In my experiments
"moveToThread (this)" works correctly and does what I intend.
(So maybe the problem is with one's intentions / expectations,
rather than with moveToThread itself.)

> Thanks in advance,
>
> Etienne

On the contrary, thanks to you, for letting me stir the pot a little.

Good luck.


K. Frank



More information about the Qt-interest-old mailing list