三、耗时代码的处理 假设有这样的应用情景:点击某个button之后,需要读入并处理一幅图像,需要耗时20秒才能处理完。 在这20s内,GUI会失去效应,界面上的任何元素都无法被点击,这种情况应该怎么办?方法有两种:1、用另一个线程去处理这个耗时任务;2、在耗时任务中,不断地去处理本线程的事件循环,以保证GUI的及时响应。 for(i=0; i < 1000000; i++)
{
//QCoreApplication::processEvents(QEventLoop::AllEvents); //去处理本线程的事件循环,避免本线程被堵塞
QCoreApplication::processEvents(QEventLoop::AllEvents, 5);//如果不够频繁,可以增加第二参数来缓解卡顿
for(j=0; j < 1000000; j++)
{
//QCoreApplication::processEvents(QEventLoop::AllEvents);//处理事件循环,不建议放在这里,可能过于频繁
doSomeThing();
}
}
一般来说,processEvents()不宜被调用的过于频繁,也不宜被调用的不够频繁。过于频繁的话,一方面会使线程的响应更好,但另一方面会导致原本就耗时的任务变得更加耗时;不够频繁的话,显然可能会使GUI线程的响应变差,例如每500ms才被调用一次,那么GUI的事件循环就只能500ms才被处理一次,当然,这个问题可以通过设定processEvents()的第二个形参略微得到缓解,更好的做法是,保证被调的周期<200ms(再小一些更好,看程序需求),这样不至于肉眼可见的卡顿。 副作用:(特别注意!) 1、在点击按钮之后,这个20s的耗时任务开始执行,尚未执行完毕时,我们点击了GUI的关闭按钮,那么GUI会立即消失,但是这个耗时任务仍然会在后台执行,直到执行完毕,进程才会退出。解决办法:重写关闭事件,在关闭事件的函数中直接结束进程。 2、在点击按钮之后,这个20s的耗时任务开始执行,执行到第5秒时,我们再次点击了这个按钮,那么QT又会执行一个新的20s任务,这个新任务完成后,又会接着把第一个20s任务从上次被打断的第5秒继续执行。如果这个任务是可重入的,后果仅仅是被执行了两遍,如果任务不可重入,那情况就彻底糟糕了。解决办法:点击按钮后把这个按钮disable掉,执行完再enable
|