项目中需要串口通讯,我寻思着把需要起QTImer频繁下发的指令放到一个通讯线程里,
结果是这样实现的:
线程类:
原来这么写的run函数,(线程类里除了run函数,其他函数基本都是空的,不需要列出。。)
//构造
CommThread::CommThread(QObject* receiver) :
QThread(receiver), m_pQueryTimer(NULL),
m_pADQueryTimer(NULL), m_bTimerFlag(true),
m_receiver(receiver)
{
// qDebug() << "CommThread :" << m_receiver.data()->objectName();
}
//run
void CommThread::run()
{
m_pADQueryTimer = new QTimer;
m_pQueryTimer = new QTimer;
m_pQueryTimer->start(1200);
m_pADQueryTimer->start(3000);
connect(m_pQueryTimer, SIGNAL(timeout()),
m_receiver.data(), SLOT(slotSendStatusQueryCmd()));
connect(m_pADQueryTimer, SIGNAL(timeout()),
m_receiver.data(), SLOT(slotSendBStatusQueryCmd()));
exec();
}
这样时,信号和槽可以通信,后来因为需要控制两个Timer的启动,所以用循环和变量来写run函数,而把原来的exec()函数去掉了
void CommThread::run()
{
m_pADQueryTimer = new QTimer;
m_pQueryTimer = new QTimer;
if(!m_receiver.isNull())
{
connect(m_pQueryTimer, SIGNAL(timeout()), m_receiver.data(),
SLOT(slotSendStatusQueryCmd()),Qt::QueuedConnection);
connect(m_pADQueryTimer, SIGNAL(timeout()), m_receiver.data(),
SLOT(slotSendBStatusQueryCmd()),Qt::QueuedConnection);
}
forever
{
if(m_bSendQueryFlag)
{
qDebug()<<"m_pQueryTimer start...";
m_pQueryTimer->start(1200);
m_pADQueryTimer->start(3000);
}
if(m_pADQueryTimer->isActive() && !m_bSendQueryFlag)
{
qDebug()<<"m_pQueryTimer stop...";
m_pQueryTimer->stop();
m_pADQueryTimer->stop();
}
}
// exec();
}
结果新需求后,发送的Timeout信号就传递不到槽函数中了。。。
有些不明白,exec的作用,如果想用变量控制timer的启动停止,应该如何用循环呢?
------解决方案--------------------
对于串口和QTimer这两个慢速的东西,应该完全没必要再单独开线程。
至于QThread的问题,简单几句话不可能回答你的问题,你可以先看看
http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
------解决方案--------------------
前段时间也刚好碰到过,首先Qt的信号和槽,还有定时器都是基于Qt的事件循环的,而exec()实际上就是启动了一个事件循环,main()函数里面就可以很明显的看到,所以子线程要接收主线程发的信号,就一定要有自己的事件循环,否则槽函数是不能触发的。