一、前言
在我很久之前的文章【学习QT之多线程编程两种方式详解】中,已经论述过Qt中使用线程的两中方式了。
在子线程中,我们往往希望它干一些费时的任务,所以经常会需要使用死循环。也许你会想到如下写法:
void run()
{
while(1) {
//子线程执行任务
}
}
或者是
bool runFlag;
void run()
{
while(runFlag) {
//子线程执行任务
}
}
- 方法1:倾向于单片机死循环的写法,但是这种写法实测是无法关闭线程的,使用
stop()
、exit()
都无法关闭线程; - 方法2:使用标志变量,我们可以通过改变标志变量的状态,来控制子线程任务的执行,这个方法比方法1要好一点,但是也无法精准的控制子线程
二、官方推荐方法
- 采用
isInterruptionRequested()
方法控制线程是否停止,该方法只有qt5才具备; - 采用锁
m_mutex
来决定线程是否暂停。 - 用一个while循环使子线程一直处于运行状态。
- 如果该线程上运行的任务应该停止,则返回true。可以通过
requestinterrupt()
请求中断。
线程类
#ifndef TESTTHREAD_H
#define TESTTHREAD_H
#include <QThread>
#include <QDebug>
#include <QMutex>
#include <QDateTime>
class TestThread : public QThread
{
Q_OBJECT
public:
TestThread();
QMutex m_mutex; //锁
void pause(); //暂停
void resume(); //继续
void exitThread(); //结束
protected:
void run();
};
#endif // TESTTHREAD_H
#include "testthread.h"
TestThread::TestThread()
{
}
void TestThread::run()
{
while (!this->isInterruptionRequested()) {
QMutexLocker lock(&m_mutex);
// to do something
qDebug()<<QDateTime::currentDateTime();
msleep(200);
}
}
void TestThread::pause()
{
m_mutex.lock();
}
void TestThread::resume()
{
m_mutex.unlock();
}
void TestThread::exitThread()
{
this->requestInterruption();
}
主类调用线程类
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <qDebug>
#include "testthread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public:
TestThread* testThread{nullptr};
private slots:
void on_pushButton_start_clicked();
void on_pushButton_pause_clicked();
void on_pushButton_resume_clicked();
void on_pushButton_exit_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_start_clicked()
{
testThread = new TestThread;
testThread->start();
}
void MainWindow::on_pushButton_pause_clicked()
{
if(!testThread) {
return;
}
testThread->pause();
}
void MainWindow::on_pushButton_resume_clicked()
{
if(!testThread) {
return;
}
testThread->resume();
}
void MainWindow::on_pushButton_exit_clicked()
{
if(!testThread) {
return;
}
testThread->exitThread();
testThread->wait();
delete testThread;
testThread = nullptr;
}