Qt之延时总结

摘要:
Q线程::msleep;//阻塞延迟50ms2,使用计时器:dead wait voidDelay_MSec_ Suspend{QTime_timer=QTime::currentTime().addMSecs;while;}2、非阻塞延迟的原理无非是使用事件循环。有两个原则:1.处理此线程的事件循环正在等待,并不断将其强制到当前线程的事件环中,以便可以处理所有被阻止的事件,从而避免程序陷入void Delay_MSec{QTime_Timer=QTime::currentTime().addMSecs;whileQCoreApplication::processEvents;}QCoreApplication::processEvents此语句使程序能够在while等待期间处理此线程的事件循环。事件循环必须返回此语句最多100毫秒。如果该过程提前完成,将立即返回该语句。

一、阻塞型延时
阻塞的原理就是:在延时期间,本线程的事件循环得不到执行。

1、QThread类的sleep()
最简单的延时方法就是使用QThread类的sleep(n)、msleep(n)、usleep(n),这几个函数的不良后果就是,GUI会在延时的时间段内失去响应,界面卡死,所以,这三个函数一般用在非GUI线程中。

QThread::msleep(50);//阻塞延时50ms


2、使用定时器:死等

  1.  
    void Delay_MSec_Suspend(unsigned int msec)
  2.  
    {    
  3.  
        QTime _Timer = QTime::currentTime().addMSecs(msec);
  4.  
        while( QTime::currentTime() < _Timer );
  5.  
    }


二、非阻塞延时
原理无非就是利用事件循环,有两种原理:

1、处理本线程的事件循环
在等待中,不断强制进入当前线程的事件循环,这样可以把堵塞的事件都处理掉,从而避免程序卡死

  1.  
    void Delay_MSec(unsigned int msec)
  2.  
    {
  3.  
        QTime _Timer = QTime::currentTime().addMSecs(msec);
  4.  
        while( QTime::currentTime() < _Timer )
  5.  
            QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
  6.  
    }

QCoreApplication::processEvents(QEventLoop::AllEvents, 100);//这条语句能够使程序在while等待期间,去处理一下本线程的事件循环,处理事件循环最多100ms必须返回本语句,如果提前处理完毕,则立即返回这条语句。这也就导致了该Delay_MSec函数的定时误差可能高达100ms。

2、使用子事件循环
创建子事件循环,在子事件循环中,父事件循环仍然是可以执行的

  1.  
    void Delay_MSec(unsigned int msec)
  2.  
    {
  3.  
        QEventLoop loop;//定义一个新的事件循环
  4.  
        QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数
  5.  
        loop.exec();//事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
  6.  
    }


三、耗时代码的处理
假设有这样的应用情景:点击某个button之后,需要读入并处理一幅图像,需要耗时20秒才能处理完。

在这20s内,GUI会失去效应,界面上的任何元素都无法被点击,这种情况应该怎么办?方法有两种:1、用另一个线程去处理这个耗时任务;2、在耗时任务中,不断地去处理本线程的事件循环,以保证GUI的及时响应。

这里重点说一下第2种,参考https://blog.csdn.net/dbzhang800/article/details/6554104

  1.  
    for(i=0; i < 1000000; i++)
  2.  
    {
  3.  
        //QCoreApplication::processEvents(QEventLoop::AllEvents);    //去处理本线程的事件循环,避免本线程被堵塞
  4.  
        QCoreApplication::processEvents(QEventLoop::AllEvents, 5);//如果不够频繁,可以增加第二参数来缓解卡顿
  5.  
     
  6.  
        for(j=0; j < 1000000; j++)
  7.  
        {
  8.  
            //QCoreApplication::processEvents(QEventLoop::AllEvents);//处理事件循环,不建议放在这里,可能过于频繁
  9.  
            doSomeThing();
  10.  
        }
  11.  
    }

四、Qt自带延时

  1.  
    #include <synchapi.h>
  2.  
    synchapi.h是Qt自带的头文件
  3.  
     
  4.  
     
  5.  
    Sleep(40);延迟40毫秒


一般来说,processEvents()不宜被调用的过于频繁,也不宜被调用的不够频繁。过于频繁的话,一方面会使线程的响应更好,但另一方面会导致原本就耗时的任务变得更加耗时;不够频繁的话,显然可能会使GUI线程的响应变差,例如每500ms才被调用一次,那么GUI的事件循环就只能500ms才被处理一次,当然,这个问题可以通过设定processEvents()的第二个形参略微得到缓解,更好的做法是,保证被调的周期<200ms(再小一些更好,看程序需求),这样不至于肉眼可见的卡顿。

副作用:(特别注意!)

1、在点击按钮之后,这个20s的耗时任务开始执行,尚未执行完毕时,我们点击了GUI的关闭按钮,那么GUI会立即消失,但是这个耗时任务仍然会在后台执行,直到执行完毕,进程才会退出。解决办法:重写关闭事件,在关闭事件的函数中直接结束进程。

2、在点击按钮之后,这个20s的耗时任务开始执行,执行到第5秒时,我们再次点击了这个按钮,那么QT又会执行一个新的20s任务,这个新任务完成后,又会接着把第一个20s任务从上次被打断的第5秒继续执行。如果这个任务是可重入的,后果仅仅是被执行了两遍,如果任务不可重入,那情况就彻底糟糕了。解决办法:点击按钮后把这个按钮disable掉,执行完再enable

转载链接:https://blog.csdn.net/qq_31073871/article/details/80472347 

免责声明:文章转载自《Qt之延时总结》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇50个c/c++源代码网站sql批量删除wordpress所有日志修订revision下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

实现一个双缓冲队列

在生产者-消费者模式中,我们常常会使用到队列,这个队列在多个线程共享访问时存在互斥和竞争操作, 意味着每次访问都要加锁。如何更好的如何减少锁竞争次数呢 ?今天要介绍的双缓冲队列就是个不错的选择。 双缓冲队列就是冲着同步/互斥的开销来的。我们知道,在多个线程并发访问同一个资源的时候,需要特别注意线程的同步问题。稍稍不注意,噢货,程序结果不正确了。 原理 直...

QT5线程关闭

QT5线程关闭 QThread析构函数的说明:请注意,删除一个QThread对象不会停止它管理的线程的执行。 删除正在运行的QThread(即isFinished()返回false)将导致程序崩溃。 在删除QThread之前等待finished()信号。 从Qt4.8起,可以释放运行刚刚结束的线程对象,通过连接finished()信号到QObject::d...

java多线程:jdk并发包的总结(转载)

转载地址:http://blog.csdn.net/yangbutao/article/details/8479520 1、java 高并发包所采用的几个机制(CAS,volatile,抽象队列同步)    CAS(乐观操作),jdk5以前采用synchronized,对共享区域进行同步操作,synchronized是重的操作,在高并发情况下,会引起线程...

Python多线程----线程池以及线程实现异步任务

Python多线程----线程池 需求:假设我们现在有一个多线程项目,每有一个用户连接进来,我们的服务器就会创建一个线程。而我们的服务器最多能够承载100个线程,再多就会崩溃。为了防止恶意用户伪装真实用户构建大量的访问来让我们的服务器崩溃,现在需要对线程数量进行限制,一共只有100个线程,并且当一个用户访问结束以后线程会自动归还,等待下一个用户访问。如果1...

深入理解Flutter多线程

Flutter默认是单线程任务处理的,如果不开启新的线程,任务默认在主线程中处理。 事件队列 和iOS应用很像,在Dart的线程中也存在事件循环和消息队列的概念,但在Dart中线程叫做isolate。应用程序启动后,开始执行main函数并运行main isolate。 每个isolate包含一个事件循环以及两个事件队列,event loop事件循环,以及e...

C++面试

https://blog.csdn.net/weixin_44363885/article/details/99567746 这一行是个 贼鸡巴重要的链接!!!   很好的总结 我直接复制到下面了: 社招:社招的同学,无论是1-3年经验,还是中途转行,都可参考。写简历必须有针对性,以后台开发为例,请去拉勾网 / 猎聘 / 智联招聘等网站,多看看后台开发的J...