SoFunction
Updated on 2025-03-04

Summary of various ways to start threads in Qt

Introduction

During the development process, using threads is a common scenario. In this article, I will sort out the five ways to use threads in Qt to facilitate later review. The first two are relatively simple, and I have mentioned them in one sentence. I will mainly introduce the next three. The last two methods are the most popular. Bloggers do not need to inherit classes. They can directly put the functions that need to be executed into the thread to run.

1. Inherit QThread and override the run function

class Thread : public QThread
{
    Q_OBJECT
public:
	virtual void run() override;
}
void Thread::run()
{
	...
}
  • Callable()Start the thread and the run function will be called automatically
  • Callable()Determine whether the thread has been started
  • Callable()Terminate thread
  • Callable()Wait for thread to terminate

2. Inheriting QObject to call moveToThread

class Test : public QObject
{
    Q_OBJECT
public:
    void test();
}
QThread th;
Test test;
(&th);

It should be noted that this method is compared with inheriting QThread.Inheriting QThread Only operations in run function are executed in thread, and all member functions in this method are executed in thread

3. Inherit the QRunnable rerun function and combine QThreadPool to implement thread pooling

#include <QObject>
#include <QRunnable>
#include <QThread>
#include <QThreadPool>
#include <QDebug>

class BPrint : public QRunnable
{
	void run()
	{
	    for ( int count = 0; count < 5; ++count )
	    {
			qDebug() << QThread::currentThread();
			QThread::msleep(1000);
	    }
	}
};

int main(int argc, char *argv[])
{
	QCoreApplication a(argc, argv);
 
	QThreadPool threadpool;	           		// Build a local thread pool	(3);        // The largest number of threads in the thread pool	
    for ( int num = 0; num < 100; ++num )
	{
	    BPrint *print;    					// Loop to build tasks that can be run in thread pools	    (print);      		// Thread pool allocates a thread to run the task	    QThread::msleep(1000);
	}
	
	return ();
}

In the above example,The QRunnable pointer we created BPrint *print does not require us to manually recycle memory. QThreadPool will clear the memory after the execution of the task is completed.

Some friends will have questions. Since there is a QThread thread class, why do you still need to use QRunnable + QThreadPool to create a thread pool to use the threading mechanism? It feels very troublesome to use. So here we want to explain the usage scenarios of this method.When the thread task volume is very large, frequent creation and release of QThread will bring a very large memory overhead, and thread pools can effectively avoid this problem

There is another problem that needs to be noted. QThread is integrated from QObject, and we usually use signal slots to communicate with the outside world.QRunnable is not inherited from the QObject class, so it cannot use the signal slot mechanism to communicate. Here are two methods,One is to useQMetaObject::invokeMethod()function. Another method is to use multiple inheritance. Custom classes need to inherit from both QRunnable and QObject.

4. Use sth::thread in C++11

#include <thread>
void threadfun1()
{
    std::cout << "threadfun1 - 1\r\n" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "threadfun1 - 2" << std::endl;
}

void threadfun2(int iParam, std::string sParam)
{
    std::cout << "threadfun2 - 1" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));
    std::cout << "threadfun2 - 2" << std::endl;
}

int main()
{
    std::thread t1(threadfun1);
    std::thread t2(threadfun2, 10, "abc");
    ();		// Wait for thread t1 to be executed    std::cout << "join" << std::endl;
    ();	// Separate thread t2 from the main thread    std::cout << "detach" << std::endl;
}

Running results:
threadfun1 - 1
threadfun2 - 1

threadfun1 - 2
join
detach

According to the output results,() will wait for the t1 thread to exit before continuing to execute. () will not wait. After the detach character is output, the main function exits, threadfun2 has not yet been executed, but after the main thread exits, the thread of t2 has also been forced to exit.

5. Qt QtConcurrent Run function

Concurrent means concurrency, QtConcurrent is a namespace.Some advanced APIs are provided so that the program written can automatically adjust the number of running threads based on the number of CPU cores of the computer. This means that future applications will continue to expand when deployed on multi-core systems in the future

The function prototype is as follows:
QFuture<T> QtConcurrent::run(Function function, ...)
QFuture<T> QtConcurrent::run(QThreadPool *pool, Function function, ...)

Simply put, the QtConcurrent::run() function is executed in a separate thread, and the thread is taken from the global QThreadPool, and the return value of the function is provided through the QFuture API.

What should be noted is:
1)The function may not run immediately; the function will only run when the thread is available
2) The QFuture returned through QtConcurrent::run() does not support cancellation or pause.The returned QFuture can only be used to query the function's run/complete status and return value.
3) Qt Concurrent has been removed from QtCore and has become an independent module, so if you want to use QtConcurrent, you need to import the module in the pro file:
QT += concurrent

There are several ways to use it:
1)Running a function in a certain thread requires extern

extern void func();
QFuture<void> future = QtConcurrent::run(func);

2)Pass parameters to this function

extern void FuncWithArguments(int arg1, const QString &amp;string);

int integer = ...;
QString string = ...;
// The parameters that need to be passed are added in sequence after the function nameQFuture&lt;void&gt; future = QtConcurrent::run(FuncWithArguments, integer, string);

3) Get the calculation result of this function

extern QString Func(const QByteArray &input);

QByteArray byte_array = ...;
QFuture<QString> future = QtConcurrent::run(func, byte_array);
...
QString result = ();

4)Constant member functions

QByteArray bytearray = "hello world";
// In a separate thread, call the constant member function split() of QByteArray, and the parameter passed to the run() function is bytearrayQFuture&lt; QList&lt;QByteArray&gt; &gt; future = QtConcurrent::run(bytearray, &amp;QByteArray::split, ',');
...
QList&lt;QByteArray&gt; result = ();

5)Noncon member functions

QImage image = ...;
// In a separate thread, call the non-const member function invertPixels() of QImage, and the parameter passed to the run() function is &imageQFuture&lt;void&gt; future = QtConcurrent::run(&amp;image, &amp;QImage::invertPixels, QImage::InvertRgba);
...
();

6)Lambda expressions

#include &lt;QFuture&gt;
#include &lt;QtConcurrent&gt;
#include &lt;QThreadPool&gt;

QThreadPool pool;
QFuture&lt;void&gt; future = QtConcurrent::run(&amp;pool, [&amp;](QObject *receiver){
    cv::Mat mat = QYImageProcessing::convertQImageToMat(image);
    cv::Mat center = cv::imread("dynaPhase_center.png");
    
    dynaPhase_alive = QYImageProcessing::getDiffPoint(mat, center);
    
    // Adaptively simulate stripes based on three points    cv::Mat ret = DynamicCarrier::DC_Adaptive_Simulation(dynaPhase_center, dynaPhase_alive, dynaPhase_align);
    ret = ret*255;
    (ret, CV_8UC1);
    QImage adaptive = QYImageProcessing::convertMatToQImage(ret);
    
    QYAlignControl *align = static_cast&lt;QYAlignControl *&gt;(receiver);
    align-&gt;callQmlGetAlivePoint(adaptive, dynaPhase_alive.x, dynaPhase_alive.y);
}, this);

This is the end of this article about five ways to start threads in Qt. For more related Qt thread content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!