Qt Multithreading and Concurrency
There are multiple ways to utilize threads in Qt. Here I show 5 ways:
1) First method is very similar to STD C++.
#include <QCoreApplication>
void hello()
{
? ? QThread::currentThread()->setObjectName("Worker Thread");
? ? qInfo() << "Hello From Worker Thread!" << QThread::currentThread();
? ? QThread::msleep(500);
? ? qInfo() << "Goodbye From Worker Thread!" << QThread::currentThread();
}
int main(int argc, char *argv[])
{
? ? QCoreApplication a(argc, argv);
? ? QThread::currentThread()->setObjectName("Main Thread");
? ? QThread *thread = QThread::create(hello);
? ? thread->start();
? ? qInfo() << "Hello From Main Thread" << QThread::currentThread();
? ? QThread::msleep(1000);
? ? qInfo() << "Goodbye From Main Thread" << QThread::currentThread();
? ? delete(thread);
? ? return a.exec();
}
2) For second method, the Concurrent library must be added to CMake:
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Concurrent)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Concurrent)
target_link_libraries(lsn2QtConcurrent Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent)
#include <QCoreApplication>
#include <QtConcurrent>
void hello()
{
? ? QThread::currentThread()->setObjectName("Worker Thread");
? ? qInfo() << "Hello From Worker Thread!" << QThread::currentThread();
? ? QThread::msleep(2000);
? ? qInfo() << "Goodbye From Worker Thread!" << QThread::currentThread();
}
int main(int argc, char *argv[])
{
? ? QCoreApplication a(argc, argv);
? ? QThread::currentThread()->setObjectName("Main Thread");
? ? QFuture<void> future = QtConcurrent::run(&hello);
? ? qInfo() << "Hello From Main Thread" << QThread::currentThread();
? ? QThread::msleep(500);
? ? qInfo() << "Blocking ..." << QThread::currentThread();
? ? future.waitForFinished();
? ? qInfo() << "Goodbye From Main Thread" << QThread::currentThread();
? ? return a.exec();
}
3) For third method, worker class must be added. Add new class named "Worker" and select QObject as Base class:
#include <QObject>
#include <QDebug>
#include <QThread>
class Worker : public QObject
{
? ? Q_OBJECT
public:
? ? explicit Worker(QObject *parent = nullptr);
? ? ~Worker();
signals:
public slots:
? ? void work();
};
#include "worker.h"
Worker::Worker(QObject *parent)
? ? : QObject{parent}
{
}
Worker::~Worker()
{
}
void Worker::work()
{
? ? QThread::currentThread()->setObjectName("Worker Thread");
? ? qInfo() << "Hello From Worker Thread!" << QThread::currentThread();
? ? QThread::msleep(1000);
? ? qInfo() << "Goodbye From Worker Thread!" << QThread::currentThread();
}
#include <QCoreApplication>
#include <QThread>
#include "worker.h"
int main(int argc, char *argv[])
{
? ? QCoreApplication a(argc, argv);
? ? QThread::currentThread()->setObjectName("Main Thread");
? ? QThread thread;
? ? thread.setObjectName("Worker Thread");
? ? Worker *worker = new Worker();
? ? worker->moveToThread(&thread);
? ? thread.connect(&thread,&QThread::started, worker, &Worker::work);
? ? thread.start();
? ? qInfo() << "Hello From Main Thread" << QThread::currentThread();
? ? QThread::msleep(500);
? ? qInfo() << "Goodbye From Main Thread" << QThread::currentThread();
? ? return a.exec();
}
?
领英推荐
4) There is more polished way of doing third method. It's to use QThread as a base class for "Worker" class and then inserting run function. Add new class named "Worker" and select <Custom> QThread as a base class:
#include <QThread>
#include <QDebug>
class Worker : public QThread
{
public:
? ? explicit Worker(QObject *parent = nullptr);
? ? // QThread interface
protected:
? ? void run() override;
};
#include "worker.h"
#include "qdebug.h"
Worker::Worker(QObject *parent)
? ? : QThread{parent}
{
}
void Worker::run()
{
? ? QThread::currentThread()->setObjectName("Worker Thread");
? ? qInfo() << "Hello From Worker Thread!" << QThread::currentThread();
? ? QThread::msleep(1000);
? ? qInfo() << "Goodbye From Worker Thread!" << QThread::currentThread();
}
#include <QCoreApplication>
#include <QThread>
#include "worker.h"
int main(int argc, char *argv[])
{
? ? QCoreApplication a(argc, argv);
? ? QThread::currentThread()->setObjectName("Main Thread");
? ? Worker *worker = new Worker();
? ? worker->start();
? ? qInfo() << "Hello From Main Thread" << QThread::currentThread();
? ? QThread::msleep(500);
? ? qInfo() << "Goodbye From Main Thread" << QThread::currentThread();
return a.exec();
}
5) The last method uses QThreadPool and QRunnable. Add new class named "Worker" and select QRunnable as its base class then insert run function of QRunnable class.
#include <QRunnable>
class Worker : public QRunnable
{
public:
? ? Worker();
? ? // QRunnable interface
public:
? ? void run() override;
};
#include "worker.h"
#include "qdebug.h"
Worker::Worker()
{
}
void Worker::run()
{
? ? QThread::currentThread()->setObjectName("Worker Thread");
? ? qInfo() << "Hello From Worker Thread!" << QThread::currentThread();
? ? QThread::msleep(1000);
? ? qInfo() << "Goodbye From Worker Thread!" << QThread::currentThread();
}
#include <QCoreApplication>
#include <QThreadPool>
#include "worker.h"
int main(int argc, char *argv[])
{
? ? QCoreApplication a(argc, argv);
? ? QThread::currentThread()->setObjectName("Main Thread");
? ? QThreadPool thread;
? ? thread.setObjectName("Worker Thread");
? ? Worker *worker = new Worker();
? ? thread.start(worker);
? ? qInfo() << "Hello From Main Thread" << QThread::currentThread();
? ? QThread::msleep(500);
? ? qInfo() << "Goodbye From Main Thread" << QThread::currentThread();
? ? return a.exec();
}
I tried to make examples as simple as possible so there are some caveats regarding pointers. One can use QScopedPointer<> or signal and slots with deleteLater() or setAutoDelete(true) options as they relish.