目录
当循环时间小于槽函数时间时:
当循环间隔时间大于槽函数时间时:
当存在两个定时器器,其中一个还是间隔100ms,另一个间隔1000ms:
当两个定时器的循环周期大于槽函数执行时间时
当在主程序中添加一个for循环后
当在for循环中加上人为触发其他事件QCoreApplication::processEvents() 后
当把for循环放到子线程中运行时
当在子线程中定义定时器时
当循环时间小于槽函数时间时:
#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>
void timer1()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 1" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 2" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 3" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 4" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 5" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 6" << std::endl;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer timeTest;
timeTest.setTimerType(Qt::PreciseTimer);
QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });
timeTest.start(100);
return a.exec();
}
执行结果:
结果分析:
QTimer 设置的循环时间小于槽函数的执行时间时,当循环时间结束时,并不会将槽函数中断,而是等槽函数运行结束后,直接再次进入,中间没有间隔时间。
当循环间隔时间大于槽函数时间时:
#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>
void timer1()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 1" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 2" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 3" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 4" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 5" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 6" << std::endl;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer timeTest;
timeTest.setTimerType(Qt::PreciseTimer);
QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });
timeTest.start(7000);
return a.exec();
}
结果分析:
间隔时间都比较准。每次的间隔时间也不会存在累计误差。
当存在两个定时器器,其中一个还是间隔100ms,另一个间隔1000ms:
#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>
void timer1()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 1" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 2" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 3" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 4" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 5" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 6" << std::endl;
}
void timer2()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " Timer2" << std::endl;
//QThread::msleep(1000);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer timeTest,timeTest2;
timeTest.setTimerType(Qt::PreciseTimer);
timeTest2.setTimerType(Qt::PreciseTimer);
QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });
QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });
timeTest.start(100);
timeTest2.start(1000);
return a.exec();
}
结果分析:
第一个100ms的定时器优先抢占触发事件,当执行完两个对应槽函数后,第二个1000ms的定时器才执行一次槽函数。
100ms触发
1s-2s-3s-4s-5s-6s-1s-2s-3s-4s-5s-6s-第二个触发-
总结:在不能确定定时器槽函数执行时间时,如果还存在其他定时器,当第一个定时器执行超时时,将直接影响第二个定时器的执行周期。所以在这种应用中,尽量避免定时器的循环周期小于槽函数执行时长。
当两个定时器的循环周期大于槽函数执行时间时
#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>
void timer1()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 1" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 2" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 3" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 4" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 5" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 6" << std::endl;
}
void timer2()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " Timer2" << std::endl;
//QThread::msleep(1000);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer timeTest,timeTest2;
timeTest.setTimerType(Qt::PreciseTimer);
timeTest2.setTimerType(Qt::PreciseTimer);
QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });
QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });
timeTest2.start(1000);
timeTest.start(7000);
return a.exec();
}
结果分析:
当两个定时器在同一个线程中时,两个定时器是按单线程串行的方式执行,当其中一个定时器触发时,必须等待当前定时器执行完成后,才有可能执行另外的定时器,两个定时器的优先级感觉是随机的。这也就解释了为什么上个案例定时周期不稳定的原因。
当在主程序中添加一个for循环后
#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>
void timer1()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 1" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 2" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 3" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 4" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 5" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 6" << std::endl;
}
void timer2()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " Timer2" << std::endl;
//QThread::msleep(1000);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer timeTest,timeTest2;
timeTest.setTimerType(Qt::PreciseTimer);
timeTest2.setTimerType(Qt::PreciseTimer);
QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });
QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });
timeTest2.start(1000);
timeTest.start(7000);
for (int i=0;i<100;++i)
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " Main"<<i << std::endl;
QThread::msleep(100);
}
return a.exec();
}
结论:两个定时器必须在for循环执行完成后,才能触发。再次 证明定时器在主线程中是以串行的方式执行。 当for循环没有结束时,定时器的timeout信号在线程中是阻塞的状况,是无法响应对应槽函数的。
当在for循环中加上人为触发其他事件QCoreApplication::processEvents() 后
#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>
void timer1()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 1" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 2" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 3" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 4" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 5" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 6" << std::endl;
}
void timer2()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " Timer2" << std::endl;
//QThread::msleep(1000);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer timeTest,timeTest2;
timeTest.setTimerType(Qt::PreciseTimer);
timeTest2.setTimerType(Qt::PreciseTimer);
QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });
QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });
timeTest2.start(1000);
timeTest.start(7000);
for (int i=0;i<100;++i)
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " Main"<<i << std::endl;
//适当的位置,插入一个processEvents,保证事件循环被处理
QCoreApplication::processEvents();
QThread::msleep(100);
}
return a.exec();
}
结论:当添加了 QCoreApplication::processEvents();后 在每次的for循环中都触发一次进程事件,保证timeout事件触发,是可行的。
当把for循环放到子线程中运行时
#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>
void timer1()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 1" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 2" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 3" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 4" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 5" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 6" << std::endl;
}
void timer2()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " Timer2" << std::endl;
//QThread::msleep(1000);
}
class TestThread1:public QThread
{
//Q_OBJECT
public:
TestThread1() {
};
~TestThread1() {
};
void run()
{
for (int i=0;i<1000;++i)
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " subThread"<<i << std::endl;
//适当的位置,插入一个processEvents,保证事件循环被处理
//QCoreApplication::processEvents();
QThread::msleep(100);
}
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer timeTest,timeTest2;
timeTest.setTimerType(Qt::PreciseTimer);
timeTest2.setTimerType(Qt::PreciseTimer);
QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });
QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });
timeTest2.start(1000);
timeTest.start(7000);
TestThread1* test1{nullptr};
test1 = new TestThread1;
test1->start();
// for (int i=0;i<100;++i)
// {
// std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " Main"<<i << std::endl;
适当的位置,插入一个processEvents,保证事件循环被处理
//QCoreApplication::processEvents();
// QThread::msleep(100);
// }
return a.exec();
}
结论:当在子线程中运行时,两个定时器能正常按预想的方式运行
当在子线程中定义定时器时
#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>
void timer1()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 1" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 2" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 3" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 4" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 5" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<" 6" << std::endl;
}
void timer2()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " Timer2" << std::endl;
//QThread::msleep(1000);
}
void timer3()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " subThreadTime3_1" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " subThreadTime3_2" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " subThreadTime3_3" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " subThreadTime3_4" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " subThreadTime3_5" << std::endl;
QThread::msleep(1000);
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " subThreadTime3_6" << std::endl;
}
void timer4()
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " subThreadTimer4" << std::endl;
//QThread::msleep(1000);
}
class TestThread1:public QThread
{
//Q_OBJECT
public:
TestThread1() {
};
~TestThread1() {
};
void run()
{
QTimer time3;
QTimer time4;
time3.setTimerType(Qt::PreciseTimer);
time4.setTimerType(Qt::PreciseTimer);
QObject::connect(&time3, &QTimer::timeout, [=]() {timer3(); });
QObject::connect(&time4, &QTimer::timeout, [=]() {timer4(); });
time3.start(1000);
time4.start(7000);
for (int i=0;i<1000;++i)
{
std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " subThread"<<i << std::endl;
//适当的位置,插入一个processEvents,保证事件循环被处理
QCoreApplication::processEvents();
QThread::msleep(100);
}
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer timeTest,timeTest2;
timeTest.setTimerType(Qt::PreciseTimer);
timeTest2.setTimerType(Qt::PreciseTimer);
QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });
QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });
timeTest2.start(1000);
timeTest.start(7000);
TestThread1* test1{nullptr};
test1 = new TestThread1;
test1->start();
// for (int i=0;i<100;++i)
// {
// std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << " Main"<<i << std::endl;
适当的位置,插入一个processEvents,保证事件循环被处理
//QCoreApplication::processEvents();
// QThread::msleep(100);
// }
return a.exec();
}
结论:当在子线程中定义定时器时,现象跟在主线程的现象一致。
QCoreApplication::processEvents();
QThread::msleep(100); 这暂停很关键,不同的暂停时间,对其他事件的影响很大,如果没有这个暂停时间,:processEvents()将无效,暂停时间越短,其他事件执行的几率就越小。在实际的应用中需要是个合适的延时。