一 QTimer详解
QTimer类提供了重复和单次触发信号的定时器。
a.void timeout ()定时器超时后,这个信号被发射。
b.void start()开启定时器,它的重载函数void start(int msec),启动或重新启动一个超时时间间隔为毫秒的定时器,如果定时器正在运行,它将被停止和重新启动。
c.void stop()停止定时器.
d.void setInterval(int msec)设置超时间隔(毫秒为单位)。
示例:
QTimer *timer = new QTimer(this);connect(timer, SIGNAL(timeout()), this, SLOT(update()));timer->start(1000);//start之后,每隔一秒触发一次槽函数
注:以前一直以为开启一个定时器就是开启了个线程,好愚蠢的我!
在一个线程内创建了多个定时器,定时器使用时注意其两个特性:
1、定时器之间不是并行处理数据,而是分片占用主线程资源 ,且定时器完成其对应的slot函数任务后,下一个定时器才会开始执行其slot函数任务;
2、当定时器的间隔时间小于其slot函数任务的执行时间时,一旦定时器timeout时,其slot函数不会终止执行,只是暂停,内部变量仍然保存,而后继续执行。
所以开启一个定时器并不等于开启了个线程
想知道时间片是什么的小伙伴可以看看这个 CPU时间分片、多线程、并发和并行
二 在多线程中开启定时器的示例
示例:达到的效果,开启多个线程执行同一个耗时的操作,每个线程里,每隔多少时间去执行这个操作.
//调用示例QTimerThread *testObject = new QTimerThread(1);//创建几个线程testObject->createItem();//调用开始创建线程的函数testObject->startMultThread();//开启线程的函数
.h
#ifndef QTIMERTHREAD_H
#define QTIMERTHREAD_H
#include <QThread>
#include <QList>
#include <QTimer>
#include "tcpclient.h"
class QTimerThread : public QObject
{Q_OBJECT
public:QTimerThread(int iCount);~QTimerThread();void createItem();void startMultThread();
public slots:void update();
private:int m_iThreadCount;//开启的线程个数QList<QTimer*> m_qTimerList;QList<QThread*> m_threadList;
};#endif // QTIMERTHREAD_H
.cpp
#include "qtimerthread.h"
#include <QDebug>
QTimerThread::QTimerThread(int iCount)
{m_iThreadCount = iCount;
}QTimerThread::~QTimerThread()
{//对象的销毁顺序也很重要for(int i = 0; i < m_iThreadCount; i++){m_threadList.value(i)->quit();m_threadList.value(i)->wait();m_qTimerList.value(i)->deleteLater();m_threadList.value(i)->deleteLater();}
}void QTimerThread::createItem()
{for(int i = 0;i < m_iThreadCount;i++){QTimer *timer = new QTimer();QThread *thread = new QThread();m_qTimerList.append(timer);m_threadList.append(thread);}
}void QTimerThread::startMultThread()
{for(int i = 0; i < m_qTimerList.size(); i++){//划重点的部分/*注:好像还有其他方式可以实现比如把定时器的开启放在connect里面,感兴趣的小伙伴可以试一试换换顺序这些的是什么效果,我当时好像都试了一遍,但是可能是这种方法比较容易理解且不出错才采用了,实践出真知。*/m_qTimerList.value(i)->start(5000);m_qTimerList.value(i)->moveToThread(m_threadList.value(i));QObject::connect(m_qTimerList.value(i),SIGNAL(timeout()),this,SLOT(update()),Qt::QueuedConnection);m_threadList.value(i)->start(); }
}void QTimerThread::update()
{//这里放需要耗时的操作
}
注:定时器的开启要放在最前面,不然会报错
翻译:QObject::startTimer: QTimer只能用于以QThread启动的线程
注意:
1)QTimer 不能指定parent, 否则 会出现警告 " QObject::moveToThread: Cannot move objects with a parent"。 因为moveToThread 无法移动有parent的object.
2) QTimer 需要用moveToThread 来改变线程相关性. 这样emit signal的时候才会在工作线程.
3)定时器的创建和开启只能在同一个线程中,不然就会报上面的那种错误。
或许你会感兴趣的内容:
Qt封装一个类管理moveToThread( )正确的开启多线程、安全的退出线程的实例
总结:QT 多线程(处理密集时的界面响应保持)注:这里面有讲moveToThread开启线程的方法,很详细了
QT-TCP服务端开启多个线程处理收到多客户端发来的消息示例