I hope that the contents of the event loop in the previous chapter have not knocked you around. This chapter will go back to the relevant content on the thread. In the previous chapters we learned about QThread
the simple use of classes. However, QT provides a thread-specific class that is not so simple, otherwise we do not need to repeatedly emphasize the use of threads must be extremely careful, a careless will fall into the trap.
In fact, QT support for threading can be traced back to QT 2.2, which was released on September 22, 2000. In this release, Qt was introduced QThread
. However, support for threads was not turned on by default at the time. Starting with Qt 4.0, threading becomes the default turn-on option for all platforms (which means that if you don't need a thread, you can turn it off by compiling the option, but that's not our point now). Now that the version of Qt introduces many classes to support threading, we will begin to understand them.
QThread
Is the first class that we will cover in detail. It is also the core class in the Qt threading class. Because of the cross-platform nature of Qt, QThread
all platform-related code should be hidden.
As we said earlier, to use QThread
start a thread, we can create a subclass of it and then overwrite its QThread::run()
function:
C + +
12345678 |
class Thread : Public qthread {protected: void run() {/ * Thread-related code * / }}; |
We then use the new class to start a new thread:
C + +
12 |
thread *thread = new thread thread ->start (;< Span class= "crayon-h" > //start new thread with start () |
Note that starting with Qt 4.4 is QThread
no longer an abstract class. QThread::run()
is no longer a pure virtual function, but a default implementation. The default implementation is actually simply invoking the function, and QThread::exec()
this function, as we said earlier, is actually starting an event loop (further elaboration of this implementation, which we'll cover in more detail in a later chapter).
QRunnable
Is the second class we are going to introduce. This is a lightweight abstract class that is used to start a task for another thread. This task is discarded after it has been run. Since this class is an abstract class, we need to inherit QRunnable
and then rewrite its pure virtual function QRunnable::run()
:
C + +
12345678 |
class Task : public qrunnable { public: void Run () { /* Thread related code */ }; |
To actually execute an QRunnable
object, we need to use the QThreadPool
class. As the name implies, this class is used to manage a thread pool. By calling the QThreadPool::start(runnable)
function, we QRunnable
put an object into QThreadPool
the execution queue. Once the threads are available, the thread pool will select an QRunnable
object and then start execution on that one. All Qt applications have a global thread pool that we can use to QThreadPool::globalInstance()
get the global thread pool, while we can create our own private thread pool and manage it manually.
It is important to note that it is QRunnable
not one QObject
, so there is no mechanism for the built-in interaction with other components. In order to interact with other components, you must write your own low-level Hodohara language, such as using the mutex daemon to obtain results.
QtConcurrent
Is the last object we want to introduce. This is a high-level API that is built to QThreadPool
handle most common parallel computing patterns: map, reduce, and filter. It also provides QtConcurrent::run()
functions for running a function on another thread. Note that a QtConcurrent
namespace is not a class, so all of its functions are global functions within the namespace.
Unlike QThread
and QRunnable
, QtConcurrent
we do not require the use of low-level synchronization primitives: All QtConcurrent
return an QFuture
object. This object can be used to query the current operation state (i.e. the task's progress), can be used to pause/reply/Cancel the task, of course, can also be used to obtain the results of the operation. Note that not all QFuture
objects support paused or canceled operations. For example, QtConcurrent::run()
objects returned by the QFuture
object cannot be canceled, but QtConcurrent::mappedReduced()
are returned by a yes. QFutureWatcher
classes are used to monitor QFuture
progress, and we can interact with the signal slots QFutureWatcher
(note, QFuture
nor inherit QObject
).
Below we can compare the three types described above:
Characteristics |
QThread |
QRunnable |
QtConcurrent |
Advanced API |
? |
? |
? |
Task oriented |
? |
? |
? |
Built support for pause/Resume/Cancel |
? |
? |
? |
Has priority |
? |
? |
? |
Can run event loops |
? |
? |
? |
QT Learning Path: QT Threading related classes