1, useQObject method to achieve multithreading

Qt has two methods for multithreading. One is to inherit the run function of QThread, and the other is to transfer a class inherited from QObject to a Thread. Before Qt4.8, the run method inherited from QThread was used, but after Qt4.8, Qt officially recommends using the second method.

The second approach to multithreading with QObject has the advantage that it supports event loops by default (many of Qt’s non-GUI classes also require event loops, such as QTimer and QTcpSocket). QThread::exec() is called in QThread::run() to provide support for message loops. Otherwise, classes that require event loops will not send signals properly. Therefore, if you want to use signals and slots, use QObject to implement multithreading directly.

Doc. Qt. IO/qt – 5 / thread…

Wiki. Qt. IO/QThreads_ge…

Wiki. Qt. IO/Threads_Eve…

 

2, with QtConcurrent: : runMethods to achieve multithreading

Doc. Qt. IO/qt – 5 / qtconc…

www.coologic.cn/2017/12/608…

2.1 Basic usage, note that the thread ID is obtained by QThread::currentThreadId();

QString id = QString::asprintf(“[%d]”, QThread::currentThreadId());

#include <QCoreApplication> #include <QDebug> #include <QList> #include <QThread> #include <QtConcurrent> void function(const QList<int> &param1, const int &param2, Qt::HANDLE main_id) { qDebug() << "function param:" << param1 << param2 << main_id; qDebug() << "function thread id:" << QThread::currentThreadId(); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QList<int> testVactor; for (int i = 1; i <= 3; i++) { testVactor.push_back(i); } qDebug() << "main thread id:" << QThread::currentThreadId(); QFuture<void> f = QtConcurrent::run(function, testVactor, 666, QThread::currentThreadId()); f.waitForFinished(); Return 0; }Copy the code

2.2 Specifying the usage of the thread pool

Sometimes you want to run a function in a global thread pool or a local thread pool instead of having Qt hosted processing, you can call it as follows:

extern void aFunction();
QThreadPool pool;
QFuture<void> future = QtConcurrent::run(&pool, aFunction);
Copy the code

QtConcurrent::run and thread pool

#include <QCoreApplication> // Qt includes #include <QtConcurrent> #include <QtCore> #include <QtGui> #include <QtNetwork> #if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0)) #include <QtWidgets> #endif QThreadPool m_threadpool; void func(void) { qDebug() << "hello"; QFuture<void> f4 = QtConcurrent::run(&m_threadpool, [&](void) { for (int i = 1000; i < 1010; i++) { qDebug() << i; Sleep(1000); }}); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Int CPU = STD ::thread::hardware_concurrency(); qDebug() << "cpu:" << cpu; m_threadpool.setMaxThreadCount(cpu); m_threadpool.setExpiryTimeout(-1); QFuture<void> f1 = QtConcurrent::run(&m_threadpool, [&](void) { for (int i = 0; i < 10; i++) { qDebug() << i; Sleep(1000); }}); QFuture<void> f2 = QtConcurrent::run(&m_threadpool, [&](void) { for (int i = 100; i < 110; i++) { qDebug() << i; Sleep(1000); }}); QFuture<void> f3 = QtConcurrent::run(func); while (true) { ; } return a.exec(); }Copy the code

2.3 An example of implementing a progress bar using QFutureWatcher

Wiki. Qt. IO/Progress_Ba…

\ Qt5.12.9 \ Examples \ Qt – 5.12.9 \ qtconcurrent \ progressdialog

A progress bar is displayed for a long time. In some time-consuming operations, we have no way to track the progress of the operation in real time, only knowing when the operation is complete. To implement a progressBar, you can use the progressBar widget and then run the action in another thread (using moveToThread). This usually requires the creation of a special object (a subclass of QObject that runs the operation and then signals Finish), which can be cumbersome if you need to do this for many different operations. However, using QFutureWatcher and QtConcurrent::run(), this is very easy. This official document demonstrates how to use this technique with QProgressDialog and QProgressBar.

If both the minimum and maximum QProgressBar values are set to 0, the progress bar displays a busy indicator instead of the current value.

 

Thread pools

3.1 Global ThreadPool QThreadPool provides a static member function, QThreadPool * globalInstance(), to obtain a global thread pool for the current process, which can be used in multiple classes.

3.2 The local thread pool can be used in the same way as the regular class. Class instantiation creates a local thread pool, maintained by the current class, to ensure that this thread pool is used only by the current class.

3.3 QThreadPool starts a thread from the QRunnable class. We need to implement the run virtual function of the QRunnable class. QRunnable autoDelete returns true by default, and you need to call setAutoDelete to change it. QRunnable has only run, Autodelete, and setautodelete functions.

3.4 Main functions

  • Int activeThreadCount() const // The current number of active threads
  • Void clear()// Clears all tasks that are currently queued but not yet running
  • Int expiryTimeout() const// A thread that is not used for a long time will automatically exit to save resources. Default value: 30000ms.
  • Int maxThreadCount() const// Maximum number of threads that can be maintained by the thread pool. Default value Number of CPU cores x 2.
  • Void expiryTimeout (int expiryTimeout) It can be set to -1. There is no timeout limit.
  • Void setMaxThreadCount(int maxThreadCount)// Sets the maximum number of threads
  • Void start(QRunnable *runnable, int priority = 0) void start(QRunnable *runnable, int priority = 0) QRunnable is passed in, and priority is the thread priority.
  • Bool waitForDone(int msecs = -1) bool waitForDone(int msecs = -1)// Wait for all threads to finish and exit

Doc. Qt. IO/qt – 5 / qthrea…

Doc. Qt. IO/qt – 5 / qrunna…

www.cnblogs.com/techiel/p/8…

3.5 Basic Usage of thread pools

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

class MyRun : public QRunnable
{
public:
    MyRun()
    {
    }

    ~MyRun()
    {
    }

public:
    void run()
    {
        int i = 3;
        while (i)
        {
            i--;
            qDebug() << "thread start:" << QThread::currentThreadId();
            QThread::msleep(500);
        }
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug() << "Main:" << QThread::currentThreadId();
    QThreadPool m;
    m.setMaxThreadCount(2);
    m.setExpiryTimeout(-1);
    MyRun *run = new MyRun;
    if (!run->autoDelete())
    {
        qDebug() << "QRunnable's autoDelete default value is not true";
        run->setAutoDelete(true);
    }

    qDebug() << m.maxThreadCount() << m.expiryTimeout();
    qDebug() << m.activeThreadCount();
    m.start(run);
    qDebug() << m.activeThreadCount();
    m.waitForDone();
    qDebug() << m.activeThreadCount();
    return 0;
}
Copy the code

3.6 Child threads in the thread pool emit signals

Need to derive QObject!

class MyThread_draw2D_SectionChart : public QObject, public QRunnable
{
	Q_OBJECT

public:
	MyThread_draw2D_SectionChart(int frameNo) :
		m_iFrameNo(frameNo)
	{
	}

	virtual ~MyThread_draw2D_SectionChart()
	{
		qDebug() << "~MyThread";
	}

public:
	virtual void run();

private:
	int m_iFrameNo;

signals:
	void sig_updateUI_SectionChart(int frameNo);
};
Copy the code

 

The child thread sends a signal to the main thread to update the UI

Through the signal slot mechanism can be achieved, child threads send signals to the main thread. It won’t block.

M_future_2d_SectionChart = QtConcurrent::run(this, &FormContent::thread_draw2D_SectionChart); Void FormContent::thread_draw2D_SectionChart(void) {qDebug() << "sub thread id:" << QThread::currentThreadId(); connect(this, SIGNAL(sig_updateUI_SectionChart()), this, SLOT(slot_updateUI_SectionChart())); While (true) {// go to the main thread to updateUI emit sig_updateUI_SectionChart(); }} void FormContent::slot_updateUI_SectionChart(void) QThread::currentThreadId(); m_pFormTimeline->updateSectionChart(); }Copy the code

 

5, data protection, lock unlock

QMutex provides mutually exclusive locks, or mutex; There are recursive and non-recursive; QMutexLocker is a helper class that automatically locks and unlocks QMutex. QReadWriterLock provides a simultaneous read lock; There are recursive and non-recursive; QReadLocker and QWriteLocker automatically lock and unlock QReadWriteLock; QSemaphore provides an integer semaphore that is a generalization of the mutex; QWaitCondition provides a way for a thread to sleep until it is awakened by another thread.

Doc. Qt. IO/qt – 5 / qmutex…

Doc. Qt. IO/qt – 5 / qmutex…

Doc. Qt. IO/qt – 5 / qreadl…

Doc. Qt. IO/qt – 5 / qwrite…

Doc. Qt. IO/qt – 5 / qreadw…

Doc. Qt. IO/qt – 5 / qsemap…

Blog.csdn.net/guoyufeng25…

 

6. Thread priority

The Priority attribute of a Qthread: Priority indicates how the system schedules the thread.

QThread::IdlePriority 0

scheduled only when no other threads are running.

QThread::LowestPriority 1

scheduled less often than LowPriority.

QThread::LowPriority 2

scheduled less often than NormalPriority.

QThread::NormalPriority 3

the default priority of the operating system.

QThread::HighPriority 4

scheduled more often than NormalPriority.

QThread::HighestPriority 5

scheduled more often than HighPriority.

QThread::TimeCriticalPriority 6

scheduled as often as possible.

QThread::InheritPriority 7

use the same priority as the creating thread. This is the default.

 

X, advanced application of multithreading

TCP Client/TCP Server

Sourceforge.net/projects/th…

Sourceforge.net/p/threader-…

Future /promise

Github.com/mhogomchung…

Y, references

Github.com/czyt1988/cz…

www.cnblogs.com/xia-weiwen/…

Github.com/Xia-Weiwen/…