说明:在复现过程中出现两点问题(1)run()函数中对m_diceValued的赋值(2)do_timeOut()函数中没有对m_seq、m_diceValued进行定义。修改后的复现程序如下所示:
主线程:
.h
#pragma once#include <QtWidgets/QMainWindow>
#include "ui_ThreadTest_one.h"
#include "QtClass.h"class ThreadTest_one : public QMainWindow//主线程
{Q_OBJECTprivate:QtClass* threadA;QTimer* timer;//新定义定时器protected:void closeEvent(QCloseEvent* event);public:ThreadTest_one(QWidget* parent = nullptr);~ThreadTest_one();private:Ui::ThreadTest_oneClass ui;public slots:void do_threadA_started();void do_threadA_finished();void on_actThread_Run_clicked();void on_actDice_Run_clicked();void on_actThread_Quit_clicked();void on_actDict_Pause_clicked();void do_timeOut();//新增定时器槽函数};
.cpp
#include "ThreadTest_one.h"
#include <QCloseEvent>
#include <QThread>
#include <QTimer>ThreadTest_one::ThreadTest_one(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);threadA = new QtClass(this);//创建工作线程connect(threadA, &QtClass::started, this, &ThreadTest_one::do_threadA_started);connect(threadA, &QtClass::finished, this, &ThreadTest_one::do_threadA_finished);timer = new QTimer(this);timer->setInterval(200);connect(timer, &QTimer::timeout, this, &ThreadTest_one::do_timeOut);}void ThreadTest_one::do_timeOut() {int tmpSeq = 0, tmpValue = 1;int m_diceValue;static int m_seq = 0;bool valid = threadA->readValue(&tmpSeq, &tmpValue);//地址做实参,值会改变if (valid&&(tmpSeq!=m_seq&&tmpSeq!=0)) {m_seq = tmpSeq;m_diceValue = tmpValue;QString str = QString::asprintf("第%d次投骰子,点数为:%d",m_seq,m_diceValue);ui.plainTextEdit->appendPlainText(str);}
}void ThreadTest_one::do_threadA_started() {ui.statusBar->showMessage("Thread状态:thread start");ui.actThread_Run->setEnabled(false);ui.actThread_Quit->setEnabled(true);ui.actDice_Run->setEnabled(true);}
void ThreadTest_one::do_threadA_finished() {ui.statusBar->showMessage("Thread状态:thread finished");ui.actThread_Run->setEnabled(true);ui.actThread_Quit->setEnabled(false);ui.actDice_Run->setEnabled(false);ui.actDict_Pause->setEnabled(false);
}//按键的槽函数
void ThreadTest_one::on_actThread_Run_clicked() {//要用clicked才能得到响应threadA->start();
}
void ThreadTest_one::on_actThread_Quit_clicked() {threadA->stopThread();
}
void ThreadTest_one::on_actDice_Run_clicked() {threadA->diceBegin();timer->start();ui.actDice_Run->setEnabled(false);ui.actDict_Pause->setEnabled(true);
}
void ThreadTest_one::on_actDict_Pause_clicked() {threadA->dicePause();timer->stop();ui.actThread_Run->setEnabled(true);ui.actDict_Pause->setEnabled(false);
}//重定义事件处理函数,确保窗口关闭时线程被停止
void ThreadTest_one::closeEvent(QCloseEvent* event) {if (threadA->isRunning()) {threadA->terminate();threadA->wait();}event->accept();
}ThreadTest_one::~ThreadTest_one()
{}
工作线程:
.h
#pragma once#include <QThread>
#include <QMutex>class QtClass : public QThread
{Q_OBJECTpublic:QtClass(QObject *parent);~QtClass();
private:int m_seq = 0; //掷骰子次数的序号int m_diceValue;//骰子的点数bool m_paused = true;//暂停投骰子bool m_stop = false;//停止线程QMutex mutex;//基于互斥量的线程同步,定义一个互斥量protected:void run();//线程的任务,线程的事件循环public:void diceBegin();//开始掷骰子void dicePause();//暂停投骰子void stopThread();//停止线程bool readValue(int *seq, int *diceValue);//供主线程读取数据的函数};
.cpp
#include "QtClass.h"
#include<QRandomGenerator>
#include<QThread>QtClass::QtClass(QObject *parent): QThread(parent)
{}
void QtClass::diceBegin() {//开始掷骰子m_paused = false;
}
void QtClass::dicePause() {//停止掷骰子m_paused = true;
}
void QtClass::stopThread() {//停止线程m_stop = true;
}
void QtClass::run() {//run函数处理事件循环m_stop = false;m_paused = true;m_seq = 0;while (!m_stop) {if (!m_paused) {mutex.lock();//锁定互斥量m_diceValue = 0;//for(int i=0;i<5;i++)m_diceValue = QRandomGenerator::global()->bounded(1, 7);//m_diceValue = m_diceValue / 5;m_seq++;mutex.unlock();//解锁互斥量}msleep(500);}quit();//退出线程
}
bool QtClass::readValue(int* seq, int* diceValue) {if (mutex.tryLock(100)) {*seq = m_seq;*diceValue = m_diceValue;mutex.unlock();return true;}elsereturn false;
}QtClass::~QtClass()
{}