尝试使用信号与槽机制实现同步。
QDiceThread线程类发送数据后进行暂停,Process类中定义信号,当数据处理完毕后发送处理完信号,QDiceThread线程类接收到信号后,再次开启数据生成。
Process类更改:
# 1. 类定义时声明信号
signals:
void processEnd(); // 主线程处理完毕
# 2. Process::Process() 中信号与槽关联
connect(this, SIGNAL(processEnd()), &threadA, SLOT(onValue_Processed()));
# 3. Process::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();
}
emit processEnd();
}
QDiceThread线程类改动:
# 1. 类定义时声明槽函数
public slots:
void onValue_Processed(); // 主线程数据处理完毕
# 2. QDiceThread::onValue_Processed() 中实现槽函数
void QDiceThread::onValue_Processed()
{
//暂停掷骰子
m_Paused=false;
qDebug()<< QDiceThread onValue_Processed(), tid : << QThread::currentThreadId();
}
# 3. QDiceThread::run() 修改
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); //发射信号
m_Paused=true; //等待主线程处理完毕
}
msleep(500); //线程休眠500ms
}
// 在 m_stop==true时结束线程任务
quit();//相当于 exit(0),退出线程的事件循环
}
运行结果:
结果并不像想象中的那样,数据只生成了一次。主线程发送的消息在子线程并未被接收。原因:子线程一直在执行msleep(500); 。
版本二:直接调用函数实现控制
QDiceThread线程类中仍在发送数据后暂停,主线程处理完后,直接使用threadA.diceBegin();设置QDiceThread线程开始。
运行结果:
虽然出了结果,但是两个线程访问了同一变量m_Paused,这个操作不是线程安全的。
传送门:qt多线程系列文章目录