moveToThread vs deriving from QThread in Qt

前端 未结 4 1024
南笙
南笙 2021-02-01 17:07

When should moveToThread be preferred over subclassing QThread?

This link shows that both methods work. On what basis should I decide what to u

4条回答
  •  猫巷女王i
    2021-02-01 17:32

    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.

提交回复
热议问题