怎么结束线程不崩溃不卡顿
1.问题描述
Qt开发客户端程序时,因为耗时的数据库查询操作会阻塞主界面线程,所以把耗时操作放入新建的子线程中去执行,用过子线程的信号和主线程的槽函数连接,返回查询结果;这样可以避免Qt程序执行耗时操作界面卡顿的问题;
但是又有新的问题,当我执行第一次查询,查询还没有结束,再用同样的线程去执行第二次查询,如果第一次查询没有结束,第二次查询m_thread->tart();将不会执行线程run函数;第二次查询无效,还是第一次查询结果;但是使用Qthread的quit(),exit();函数,也无法立刻结束掉正在执行的第一次查询;如果执行完了quit()或exit()后,就立刻执行delete m_m_thread会造成程序崩溃,线程还在执行;只有在执行完了quit()或exit()后,执行wait();函数;但是wait();会阻塞等待线程结束,线程结束后,才能delete m_thread,或者才能执行第二次查询。
但是wait();会阻塞等待线程结束,造成主线程的卡顿无响应;还是没有解决问题。这时候想到用teminate();函数直接强杀一波,teminate();会立即结束线程,立刻返回;但是teminate();是不安全的,概率性会造成异常崩溃,如下图所示,加上try catch也无济于事;
那么如何优雅的结束掉正在执行耗时任务的线程,又不影响新的查询任务的执行呢?
2.实现方法
每次执行查询任务都创建新的线程去执行新的查询,旧的线程先判断下,如果在运行,则连接信号槽finished和deletelater函数,让它执行结束后自动销毁,不去等他了;如果没有在执行我们就立刻销毁掉;执行新的查询统一用新创建的对象去执行耗时操作;这样及避免等待上一次的执行结束,导致界面卡顿,也不会影响第二次的任务执行;
if (m_CollisionQueryThread!=NULL) { if (m_CollisionQueryThread->isRunning()) { connect(m_CollisionQueryThread, &CollisionQueryThread::finished, m_CollisionQueryThread, &CollisionQueryThread::deleteLater); LOG_INFO("CollisionQueryThread stop0 "); m_CollisionQueryThread->StopTask(); m_CollisionQueryThread->quit(); //m_CollisionQueryThread->wait(); } else { delete m_CollisionQueryThread; m_CollisionQueryThread = NULL; } } //else { m_CollisionQueryThread = new CollisionQueryThread();
m_CollisionQueryThread->StopTask();函数的实现也很简单,就是将线程变量m_stop设置为true,当线程run函数中有循环时,可以直接return退出,这样线程可以早点结束,不用等到循环结束才会退出线程。
void CollisionQueryThread::StopTask()
{
m_stop = true;
}
void CollisionQueryThread::run()
{
for (int i = 0; i < retList.size(); i++) { if (m_stop==true) { LOG_INFO("CollisionQueryThread stop1 "); return; } //耗时的操作········ } }
}