目录
1、数据生成器类(QDiceThread)
2、主程序调用类(Process)
3、mian.cpp程序启动
4、信号与槽机制测试
数据生成器每隔500ms不断的生成新的数据,主线程进行处理和显示操作。main()函数中定义变量,启动线程,之后开启事件循环,等待进程结束。
实现方式:主线程中使用Process类管理业务逻辑处理。在Process类中定义QDiceThread类实例对象threadA,threadA调用自身函数实现QDiceThread线程类的开启、关闭、暂停,QDiceThread线程类的run函数中不断产生新的数据,通过信号与槽机制,发送至Process类,Process类onthreadA_newValue槽函数接收到数据后显示。
其中,控制变量:m_Paused, m_stop控制run()函数中线程循环的暂停、结束。m_seq、m_diceValue为产生的数据,掷骰子次数及骰子点数,可在调用方直接访问也可通过emit信号当改变后直接发送给接收槽函数。
qdice_thread.h
#ifndef QDICE_THREAD_H
#define QDICE_THREAD_H
#include
class QDiceThread : public QThread
{
Q_OBJECT
public:
QDiceThread();
void diceBegin();//掷一次骰子
void dicePause();//暂停
void stopThread(); //结束线程
private:
int m_seq=0;//掷骰子次数序号
int m_diceValue;//骰子点数
bool m_Paused=true; //掷一次骰子
bool m_stop=false; //停止线程
protected:
void run() Q_DECL_OVERRIDE; //线程任务
signals:
void newValue(int seq,int diceValue); //产生新点数的信号
};
#endif // QDICE_THREAD_H
qdice_thread.cpp
#include qdice_thread.h
#include
#include
#include
QDiceThread::QDiceThread():m_Paused(false)
{
}
void QDiceThread::diceBegin()
{
//开始掷骰子
m_Paused=false;
qDebug()<< "QDiceThread diceBegin(), tid : " << QThread::currentThreadId();
}
void QDiceThread::dicePause()
{
//暂停掷骰子
m_Paused=true;
}
void QDiceThread::stopThread()
{
//停止线程
m_stop=true;
qDebug()<< "QDiceThread stopThread(), tid : " << QThread::currentThreadId();
}
void QDiceThread::run()
{
qDebug()<< "QDiceThread run(), tid :" << QThread::currentThreadId();
//线程任务
m_stop=false;//启动线程时令m_stop=false
m_seq=0; //掷骰子次数
qsrand(QTime::currentTime().msec());//随机数初始化,qsrand是线程安全的
while(!m_stop)//循环主体
{
if (!m_Paused)
{
m_diceValue=qrand(); //获取随机数
m_diceValue=(m_diceValue % 6)+1;
m_seq++;
qDebug() << "emit newValue:" << m_seq << m_diceValue
<< "tid : "<< QThread::currentThreadId();;
emit newValue(m_seq, m_diceValue); //发射信号
}
msleep(500); //线程休眠500ms
}
// 在 m_stop==true时结束线程任务
quit();//相当于 exit(0),退出线程的事件循环
}
实现对处理过程的封装。其中,控制变量:m_Paused, m_stop控制run()函数中线程循环的暂停、结束。m_seq、m_diceValue为产生的数据,掷骰子次数及骰子点数,可在调用方直接访问也可通过emit信号当改变后直接发送给接收槽函数。
process.h
#ifndef PROCESS_H
#define PROCESS_H
#include
#include qdice_thread.h
class Process: public QObject
{
Q_OBJECT
public:
Process();
// explicit Process(QObject *parent = nullptr);
private:
QDiceThread threadA;
public:
void startThread(); // 启动线程
void stopThread(); // 停止线程
public slots:
void onthreadA_started();
void onthreadA_finished();
void onthreadA_newValue(int seq, int diceValue);
};
#endif // PROCESS_H
process.cpp
#include process.h
#include
#include
Process::Process()
{
connect(&threadA, SIGNAL(started()), this, SLOT(onthreadA_started()));
connect(&threadA, SIGNAL(finished()), this, SLOT(onthreadA_finished()));
connect(&threadA, SIGNAL(newValue(int,int)), this, SLOT(onthreadA_newValue(int,int)));
qDebug()<< Process Process(), tid : << QThread::currentThreadId();
}
//Process::Process(QObject *parent):QObject(parent)
//{
// connect(&threadA, SIGNAL(started()), this, SLOT(onthreadA_started()));
// connect(&threadA, SIGNAL(finished()), this, SLOT(onthreadA_finished()));
// connect(&threadA, SIGNAL(newValue(int,int)), this, SLOT(onthreadA_newValue(int,int)));
//}
// 启动线程
void Process::startThread()
{
qDebug()<< " Process startThread(), tid : "<< QThread::currentThreadId();
threadA.moveToThread(&threadA);
threadA.diceBegin(); // 控制变量,实现线程循环开始
threadA.start(); // 线程开启,执行run()虚函数
}
// 停止线程
void Process::stopThread()
{
qDebug()<< " Process stopThread(), tid : "<< QThread::currentThreadId();
if (threadA.isRunning())
{
threadA.stopThread(); // 控制变量,实现线程循环结束
threadA.wait();// 等待线程结束
}
}
void Process::onthreadA_started()
{
qDebug()<< "Process onthreadA_started(), tid : " << QThread::currentThreadId();
}
void Process::onthreadA_finished()
{
qDebug()<< "Process onthreadA_finished(), tid : " << QThread::currentThreadId();
}
void Process::onthreadA_newValue(int seq, int diceValue)
{
qDebug()<< "Process onthreadA_newValue(), tid : " << QThread::currentThreadId();
qDebug() << "get value: seq=" << seq << ", diceValue=" << diceValue;
// sleep(1);
if (seq > 3)
{
stopThread();
}
}
其中,控制变量:m_Paused, m_stop控制run()函数中线程循环的暂停、结束。m_seq、m_diceValue为产生的数据,掷骰子次数及骰子点数,可在调用方直接访问也可通过emit信号当改变后直接发送给接收槽函数。
#include
#include qdice_thread.h
#include
#include
#include
#include
#include
#include process.h
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug()<< "mian(), tid : " << QThread::currentThreadId();
Process proc;
// 启动线程
proc.startThread();
// sleep(5);
// // 结束线程
// if (proc.m_recvCnt > 10)
// {
// proc.stopThread();
// }
return a.exec();
}
结果:
示例代码中,线程1 run函数每隔500ms产生一次数据,通过信号与槽以消息队列机制将参数传递到Peocess中,Process类onthreadA_newValue槽函数接收到数据后显示。
当onthreadA_newValue槽函数处理及时时,数据产生和数据显示线程同步,交替进行。但是存在问题:当槽函数处理不及时时,存在延迟(数据产生类并未等待数据处理完就又产生了新的数据),有时候会产生意想不到的效果。
测试代码:
void Process::onthreadA_newValue(int seq, int diceValue)
{
qDebug()<< Process onthreadA_newValue(), tid : << QThread::currentThreadId();
qDebug() << get value: seq= << seq << , diceValue= << diceValue;
sleep(1);
if (seq > 3)
{
stopThread();
}
}
测试效果:
主线程中,设置投掷3次后结束数据生成线程,结果因为处理速度慢,当主线程接收到投掷次数为3时,实际上数据生成器类已经产生8次数据。这个显然是不合理的。
传送门:qt多线程系列文章目录