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; } //耗时的操作········ } }
}

 

原文地址:http://www.cnblogs.com/bclshuai/p/16848615.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性