Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

moveToThread vs deriving from QThread in Qt

When should moveToThread be preferred over subclassing QThread?

This link shows that both methods work. On what basis should I decide what to use from those two?

like image 778
Aquarius_Girl Avatar asked May 31 '18 10:05

Aquarius_Girl


People also ask

What does moveToThread do?

moveToThread() is used to control the object's thread affinity, which basically means setting the thread (or better the Qt event loop) from which the object will emit signals and its slots will be executed.

What is QThread in Qt?

A QThread object manages one thread of control within the program. QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread. You can use worker objects by moving them to the thread using QObject::moveToThread().


1 Answers

I would focus on the differences between the two methods. There isn't a general answer that fits all use cases, so it's good to understand exactly what they are to choose the best that fits your case.

Using moveToThread()

moveToThread() is used to control the object's thread affinity, which basically means setting the thread (or better the Qt event loop) from which the object will emit signals and its slots will be executed.

As shown in the documentation you linked, this can be used to run code on a different thread, basically creating a dummy worker, writing the code to run in a public slot (in the example the doWork() slot) and then using moveToThread to move it to a different event loop.

Then, a signal connected to that slot is fired. Since the object that emits the signal (the Controller in the example) lives in a different thread, and the signal is connected to our doWork method with a queued connection, the doWork method will be executed in the worker thread.

The key here is that you are creating a new event loop, run by the worker thread. Hence, once the doWork slot has started, the whole event loop will be busy until it exits, and this means that incoming signals will be queued.

Subclassing QThread()

The other method described in Qt's documentation is subclassing QThread. In this case, one overrides the default implementation of the QThread::run() method, which creates an event loop, to run something else.

There's nothing wrong with this approach itself, although there are several catches.

First of all, it is very easy to write unsafe code, because the run() method is the only one in that class that will be actually run on another thread.

If as an example, you have a member variable that you initialize in the constructor and then use in the run() method, your member is initialized in the thread of the caller and then used in the new thread.

Same story for any public method that could be called either from the caller or inside run().

Also slots would be executed from the caller's thread, (unless you do something really weird as moveToThread(this)) leading to extra confusion.

So, it is possible, but you really are on your own with this approach and you must pay extra attention.

Other approaches

There are of course alternatives to both approaches, depending on what you need. If you just need to run some code in background while your GUI thread is running you may consider using QtConcurrent::run().

However, keep in mind that QtConcurrent will use the global QThreadPool. If the whole pool is busy (meaning there aren't available threads in the pool), your code will not run immediately.

Another alternative, if you are at the least on C++11, is to use a lower level API such as std::thread.

like image 83
Sergio Monteleone Avatar answered Sep 22 '22 10:09

Sergio Monteleone