[Interest] QThreads: There's no one way to "do it right"! :)

K. Frank kfrank29.c at gmail.com
Sat Jan 26 19:15:27 CET 2013


Hello Mandeep and Friends!

On Wed, Jan 23, 2013 at 2:42 AM, Mandeep Sandhu
<mandeepsandhu.chd at gmail.com> wrote:
> First I thought "I was doing it right"
>
> Then they said "you're doing it wrong"
> (http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/)
>
> Then I thought "I _finally_ got it right"!!
>
> Now they say "You were not doing so wrong"
> (http://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html)!! :D
> ...

Thank you so much for this post, Mandeep.  And thanks to all
for the many thoughtful -- and non-prescriptive -- comments.

And all this time I thought I was just a lone voice in the wilderness ...

I'm a little late to the party, but I can't resist commenting.

> Clearly, if done carefully, both methods work as intented.

Indeed they do.  There has, unfortunately, been a certain amount
of "you're doing it wrong" disinformation on this list that has stated
and/or implied that (for various choices of "it"):

   it's simply wrong and won't ever work
   it's so close to being simply wrong that it almost always won't work
   it's technically right, but it's such a bad idea you should never do it

The first two are technically incorrect.  The third is such a close
cousin to the first two, that it's really just as bad.

Although I don't agree with it, the only legitimate negative stance
I've seen is something like:

   the design trade-offs inherent in "it" lean enough towards the negative
   side that you should prefer other approaches

Like I said, I don't fully agree with this, but it's a justifiable view
to hold.

Now "it" can be various "you're doing it wrong" uses of QThread
but as a provocative example I have in mind subclassing QThread
and calling "moveToThread (this)" (preferably in the subclass's
constructor).

Just for the record, for the "can't work" crowd, I have a little
semi-production gui app that does some computation in the
background and uses "moveToThread (this)".  Works like a
champ, and I haven't stumbled over "bad object-oriented design"
when tweaking it over time.

In the case where your thread is not going to use signals / slots
or otherwise use a Qt event loop, then you can subclass QThread
and put your "business logic" in the overridden run method, or
you can design a separate business-logic class and
moveToThread it to a QThread.  Both work.

The first is more concise (and, as much as I hate to break it
to the object-oriented crowd, all else being equal, more concise
is better -- fewer lines of code mean fewer places an error can
creep in, fewer lines of code to read in a code review, etc.).

The second has better separation of concerns:  QThread's "job"
is to manage a thread of execution, and the business-logic
class's job is to perform business logic.  This modularization,
at the expense of extra code, means more opportunity for reuse:
the business-logic class could for example, be used in a
single-threaded app or with a thread pool.

Both approaches work, and have different trade-offs.  My view
is that for smaller, more stable, and one-off apps, the first
approach is preferable because it's a little less work.

For larger projects that are more likely to offer reuse opportunity
internally and are likely to evolve over time, paying the upfront
cost of the second, more object-oriented approach is preferable,
because that upfront investment is likely to pay off in the future.

Now the kicker:  I come to the exact same analysis when you
want signals and slots in your thread.  moveToThread (this) is
perfectly correct, works as intended, and is the natural approach
if you want to use the first approach of having your business-logic
class subclass QThread.

The trade-offs are the same, and signals and slots are a separate
orthogonal issue in the analysis.  Subclassing QThread (and using
moveToThread (this)) is more concise; creating a separate
business-logic class provides better separation of concerns.

But what about the counter-argument "If you use moveToThread (this),
you might make a mistake!"  So?  If you do any programming, you
might make s mistake.  Multi-threaded programming introduces
new issues (that might cause you to make a mistake).  Not using
moveToThread (this) doesn't make these issues go away.

> ...
> Regards,
> -mandeep

Thanks to all for the interesting discussion, and ...


Happy (Multi-Threaded) Hacking!


K. Frank



More information about the Interest mailing list