【嵌入式——QT】QThread创建多线程
- 概述
- 主要函数
- 图示
- 代码示例
概述
QThread类提供不依赖于平台的管理线程的方法,一个QThread类的对象管理一个线程,一般从QThread继承一个自定义类,并重定义虚函数run(),在run()函数里实现线程需要完成的任务。
将应用程序的线程称为主线程,额外创建的线程称为工作线程,一般在主线程里创建工作线程,并调用start()开始执行工作线程的任务。start()会在内部调用run()函数,进入工作线程的时间循环,在run()函数调用exit()或quit()可以结束线程的事件循环,或在主线程里调用terminate()强制结束线程。
主要函数
信号
- void finished():线程结束时发射此信号;
- void started():线程开始执行、run()函数被调用之前发射此信号;
槽函数
-
quit():退出线程的事件循环,并返回代码0,等效于exit(0);
-
start(QThread::Priority priority = InheritPriority):内部调用run()开始执行线程,操作系统根据Priority参数进行调度;
-
terminate():终止线程的运行,但不是立即结束线程,而是等待操作系统结束线程,使用terminate()之后应使用wait();
Priority
- QThread::IdlePriority: 仅在没有其他线程运行时调度;
- QThread::LowestPriority:比低优先级安排得更少;
- QThread::LowPriority:比NormalPriority更少被安排;
- QThread::NormalPriority:操作系统的默认优先级;
- QThread::HighPriority:比NormalPriority更经常被安排;
- QThread::HighestPriority:比高优先级安排得更频繁;
- QThread::TimeCriticalPriority:尽可能多安排时间;
- QThread::InheritPriority:使用与创建线程相同的优先级。这是默认值;
公共函数
- bool isFinished() const:线程是否结束;
- bool isRunning() const:线程是否正在运行;
- priority() const:返回线程的优先级;
- setPriority(QThread::Priority priority):设置线程的优先级;
- exit(int returnCode = 0):退出线程的事件循环;
- wait(unsigned long time):阻止线程执行,直到线程结束,或等待线程超过time毫秒;
静态公共函数
- idealThreadCount():返回系统上能运行的线程的理想个数;
- msleep(unsigned long msecs):强制当前线程休眠msecs毫秒;
- sleep(unsigned long secs):强制当前线程休眠secs秒;
- usleep(unsigned long usecs):强制当前线程休眠usecs微秒;
保护函数
- int exec():由run()函数调用,进入线程的事件循环,等待exit退出;
- virtual void run():start()调用run()函数开始线程任务的执行,所以在run()函数里实现线程的任务功能;
图示
代码示例
QDiceThread.h
#ifndef QDICETHREAD_H
#define QDICETHREAD_H#include <QObject>
#include <QThread>
#include <QMutex>
class QDiceThread : public QThread
{Q_OBJECTpublic:QDiceThread();~QDiceThread();void run() Q_DECL_OVERRIDE;void diceBegin();//掷一次骰子void dicePause();//暂停void stopThread();//结束线程bool readValue(int* seq, int* diceValue);signals:void newValue(int seq, int diceValue);//产生新点数的信号private :int m_seq = 0;//掷骰子次数序号int m_diceValue;//骰子点数bool m_paused = true;//暂停bool m_stop = false;//停止QMutex mutex;};#endif // QDICETHREAD_H
QDiceThread.cpp
#include "QDiceThread.h"
#include <QTime>
#include <QMutexLocker>
QDiceThread::QDiceThread() {}QDiceThread::~QDiceThread()
{
}void QDiceThread::run()
{m_stop = false;m_seq = 0;qsrand(QTime::currentTime().msec());while(!m_stop) {if(!m_paused) {//QMutexLocker用法// QMutexLocker Locker(&mutex);//mutex用法mutex.lock();m_diceValue = qrand();m_diceValue = (m_diceValue % 6)+1;m_seq++;//使用互斥量读取数据,暂时注释掉信号操作// emit newValue(m_seq, m_diceValue);//mutex用法mutex.unlock();}msleep(500);}quit();
}void QDiceThread::diceBegin()
{m_paused = false;
}void QDiceThread::dicePause()
{m_paused = true;
}void QDiceThread::stopThread()
{m_stop = true;
}bool QDiceThread::readValue(int* seq, int* diceValue)
{if(mutex.tryLock()) {*seq = m_seq;*diceValue = m_diceValue;mutex.unlock();return true;} else {return false;}
}
QThreadDialog.h
#ifndef QTHREADDIALOG_H
#define QTHREADDIALOG_H#include <QDialog>
#include "QDiceThread.h"
#include <QTimer>
namespace Ui
{class QThreadDialog;
}class QThreadDialog : public QDialog
{Q_OBJECTpublic:explicit QThreadDialog(QWidget* parent = nullptr);~QThreadDialog();void closeEvent(QCloseEvent* event);private slots:void on_pushButtonStart_clicked();void on_pushButtonPause_clicked();void on_pushButtonBegin_clicked();void on_pushButtonStop_clicked();void on_pushButtonClear_clicked();public slots:void threadStatusStart();void threadStatusFinished();void threadNewValue(int seq, int diceValue);void onTimeOut();private:Ui::QThreadDialog* ui;QDiceThread thread;QTimer timer;int mSeq, mDiceValue;
};#endif // QTHREADDIALOG_H
QThreadDialog.cpp
#include "QThreadDialog.h"
#include "ui_QThreadDialog.h"QThreadDialog::QThreadDialog(QWidget* parent): QDialog(parent), ui(new Ui::QThreadDialog)
{ui->setupUi(this);connect(&thread, SIGNAL(started()), this, SLOT(threadStatusStart()));connect(&thread, SIGNAL(finished()), this, SLOT(threadStatusFinished()));connect(&thread, &QDiceThread::newValue, this, &QThreadDialog::threadNewValue);connect(&timer, SIGNAL(timeout()), this, SLOT(onTimeOut()));
}QThreadDialog::~QThreadDialog()
{delete ui;
}void QThreadDialog::closeEvent(QCloseEvent* event)
{if(thread.isRunning()) {thread.stopThread();thread.wait();}event->accept();
}void QThreadDialog::on_pushButtonStart_clicked()
{thread.start();mSeq = 0;ui->pushButtonStart->setEnabled(false);ui->pushButtonStop->setEnabled(true);ui->pushButtonBegin->setEnabled(true);ui->pushButtonPause->setEnabled(false);
}void QThreadDialog::on_pushButtonStop_clicked()
{thread.stopThread();thread.wait();ui->pushButtonStart->setEnabled(true);ui->pushButtonStop->setEnabled(false);ui->pushButtonBegin->setEnabled(false);ui->pushButtonPause->setEnabled(false);
}void QThreadDialog::on_pushButtonBegin_clicked()
{thread.diceBegin();timer.start(100);ui->pushButtonBegin->setEnabled(false);ui->pushButtonPause->setEnabled(true);
}void QThreadDialog::on_pushButtonPause_clicked()
{thread.dicePause();timer.stop();ui->pushButtonBegin->setEnabled(true);ui->pushButtonPause->setEnabled(false);
}void QThreadDialog::on_pushButtonClear_clicked()
{ui->plainTextEdit->clear();
}void QThreadDialog::threadStatusStart()
{ui->labelStatus->setText("thread started");
}void QThreadDialog::threadStatusFinished()
{ui->labelStatus->setText("thread finished");
}void QThreadDialog::threadNewValue(int seq, int diceValue)
{QString str = QString::asprintf(u8"第%d次投掷骰子,点数为:%d", seq, diceValue);ui->plainTextEdit->appendPlainText(str);
}void QThreadDialog::onTimeOut()
{int tmpSeq =0, tmpValue = 0;bool valid = thread.readValue(&tmpSeq, &tmpValue);if(valid && (tmpSeq != mSeq)) {mSeq = tmpSeq;mDiceValue = tmpValue;QString str = QString::asprintf(u8"第%d次投掷骰子,点数为:%d", mSeq, mDiceValue);ui->plainTextEdit->appendPlainText(str);}
}