Qt5 Tutorial Creating QThread using QtConcurrent - 2020
In this tutorial, we will learn how to create Threads using QtConcurrent Framework.
In the previous example of creating thread from QThread is not a recommended way of using thread in Qt as we can see from the Qt5 document below:
The QtConcurrent namespace provides high-level APIs that make it possible to write multi-threaded programs without using low-level threading primitives such as mutexes, read-write locks, wait conditions, or semaphores.
Programs written with QtConcurrent automatically adjust the number of threads used according to the number of processor cores available. This means that applications written today will continue to scale when deployed on multi-core systems in the future.
In this section, we'll get the same output as in the previous the previous example, QThreads - Creating Threads with much more short and concise way.
Here is the code:
#include <QCoreApplication> #include <qtconcurrentrun.h> #include <QThread> #ifndef QT_NO_CONCURRENT void myRunFunction(QString name) { for(int i = 0; i <= 5; i++) { qDebug() << name << " " << i << "from" << QThread::currentThread(); } } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QFuture<void> t1 = QtConcurrent::run(myRunFunction, QString("A")); QFuture<void> t2 = QtConcurrent::run(myRunFunction, QString("B")); QFuture<void> t3 = QtConcurrent::run(myRunFunction, QString("C")); t1.waitForFinished(); t2.waitForFinished(); t3.waitForFinished(); return a.exec(); } #else #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QString text("Qt Concurrent is not yet supported on this platform"); QLabel *label = new QLabel(text); label->setWordWrap(true); label->show(); qDebug() << text; app.exec(); } #endif
Also, we need to add a line to .pro file like this:
QT += concurrent
Output:
"A" 0 from QThread(0xaff287a000, name = "Thread (pooled)") "B" 0 from QThread(0xaff287dd30, name = "Thread (pooled)") "A" 1 from QThread(0xaff287a000, name = "Thread (pooled)") "A" 2 from QThread(0xaff287a000, name = "Thread (pooled)") "B" 1 from QThread(0xaff287dd30, name = "Thread (pooled)") "A" 3 from QThread(0xaff287a000, name = "Thread (pooled)") "B" 2 from QThread(0xaff287dd30, name = "Thread (pooled)") "A" 4 from QThread(0xaff287a000, name = "Thread (pooled)") "B" 3 from QThread(0xaff287dd30, name = "Thread (pooled)") "A" 5 from QThread(0xaff287a000, name = "Thread (pooled)") "B" 4 from QThread(0xaff287dd30, name = "Thread (pooled)") "B" 5 from QThread(0xaff287dd30, name = "Thread (pooled)") "C" 0 from QThread(0xaff287a000, name = "Thread (pooled)") "C" 1 from QThread(0xaff287a000, name = "Thread (pooled)") "C" 2 from QThread(0xaff287a000, name = "Thread (pooled)") "C" 3 from QThread(0xaff287a000, name = "Thread (pooled)") "C" 4 from QThread(0xaff287a000, name = "Thread (pooled)") "C" 5 from QThread(0xaff287a000, name = "Thread (pooled)")
As we can see, we do not have to create a thread by ourselves. All we have to do is to define a run function with the proper parameter feeds. QtConcurrent handles all the details for us.
In this example, we used couple of APIs from QtConcurrent:
- QtConcurrent::run() - runs a function in another thread.
- QFuture - represents the result of an asynchronous computation.
Actually, QFuture also offers ways to interact with a runnning computation such as cancel(), pause(), or resume(). However, we cannot do that in our example because the future was returned by QtConcurrent::run(). We'll deal with this interaction with the result later section for QtConcurrent::mappedReduced().
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization