QT之QTimer详解以及结合多线程中开启定时器的示例

一 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 
#include 
#include 
#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 
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服务端开启多个线程处理收到多客户端发来的消息示例

你可能感兴趣的:(QT实用技巧(应用),qt,c++,开发语言,多线程)