zoukankan      html  css  js  c++  java
  • QThread线程让GUI主线程锁死问题(后来发现是打包前没有qmake和bat脚本中文编码导致的乌龙bug)

    问题描述

    GUI线程中有一些耗时操作,直接在主线程中执行会使主gui卡死,后来放在QThread线程中执行,子进程中绑定信号槽更新,用进度条显示进程执行的状态,调试的时候是正常运行的,当把程序打包出来执行,子线程开始执行会使gui线程也卡死,界面未响应状态,进度条也不再更新,很让人卧槽的问题。

    后来测试了Qt两种线程方法发现问题没有消除,最后发现问题原因是:①打包前没有qmake,导致打包的程序不是最新+②代码中试用的测试进程代码没有删除+③bat脚本中文编码导致bat没有运行,但这些问题在调试的时候正常,打包出来就全部显现,导致后来调试困难,现在记录下qt的线程开启的两种方法

    先复现我的导致问题的三个地方

    1. 打包前没有执行qmake,实际生成的exe程序比代码老

    2. 程序打包后bat脚本中文会执行失败,添加chcp 65001 申明下编码

    1. 线程执行返回中开启的测试进程代码没有删
    // 线程执行返回
    void MainWindow::handleResults(QString cmd)
    {
    
          //下面这些没删
        QProcess p(0);
        p.start("cmd", QStringList()<<"cd "+QCoreApplication::applicationDirPath()<<"python PyScript/dealJsonData.py 2");
        p.waitForStarted();
        p.waitForFinished();
        QString strTemp=QString::fromLocal8Bit(p.readAllStandardOutput());  //获得输出
    
    }
    

    Qt线程创建有两种方法,一种是继承QThread,然后重写run的方式,但是这种方式官方已经不推荐了。官方不推荐就不这样写了,推荐第二种方式。使用QObject的moveToThread方法开启线程

    1.第一种,使用QThread主线程

    线程类定义:

    #ifndef WORKERTHREAD_H
    #define WORKERTHREAD_H
    
    #include <QThread>
    #include <QMutexLocker>
    #include<QDebug>
    #include <QApplication>
    #include <QProcess>
    
    class WorkerThread : public QThread
    {
        Q_OBJECT
    
    public:
        explicit WorkerThread(QObject *parent = 0,QString cmd="")
            : QThread(parent),
              m_bStopped(false),
              commentStr(cmd)
        {
            qDebug() << "Worker Thread : " << QThread::currentThreadId();
        }
    
        ~WorkerThread()
        {
            stop();
            quit();
            wait();
        }
    
        void stop()
        {
            qDebug() << "Worker Stop Thread : " << QThread::currentThreadId();
            QMutexLocker locker(&m_mutex);
            m_bStopped = true;
        }
    
    protected:
        virtual void run() Q_DECL_OVERRIDE {
            //qDebug() << "Worker Run Thread : " << QThread::currentThreadId();
    
            int res=QProcess::execute(commentStr.toStdString().c_str());
    
            // 准备更新
            emit resultReady(commentStr);
    
            // 检测是否停止
          /*  {
                QMutexLocker locker(&m_mutex);
                if (m_bStopped)
                    return;
            }*/
            // locker超出范围并释放互斥锁
    
        }
    signals:
        void resultReady(QString value);
    
    private:
        bool m_bStopped;
        QMutex m_mutex;
        QString commentStr;
    };
    
    #endif // WORKERTHREAD_H
    
    

    线程启动

         workerThread = new WorkerThread(this,cmdXml);
         connect(workerThread, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
         // 线程结束后,自动销毁
         connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
         workerThread->start();
    

    线程执行结束响应

    // 线程执行返回
    void MainWindow::handleResults(QString cmd)
    {
       // qDebug() << "Handle Thread : " << QThread::currentThreadId();
    
       statusProgressBar->hide() ;    //隐藏状态栏进度条
        .....
    }
    

    2.第二种,使用QObject的moveToThread方法开启线程

    moveToThreadWorkThread.h

    #ifndef MOVETOTHREADWORKTHREAD_H
    #define MOVETOTHREADWORKTHREAD_H
    
    #include <QObject>
    
    class moveToThreadWorkThread : public QObject
    {
        Q_OBJECT
    public:
        explicit moveToThreadWorkThread(QObject *parent = nullptr,QString cmd="");
        ~moveToThreadWorkThread();
    
    public slots:
        void start1();
        void doWork();
    signals:
        void workFinished();
        void workStart();
        void resultReady(QString value);
    private:
        QString commentStr;
    };
    
    #endif // MOVETOTHREADWORKTHREAD_H
    
    

    moveToThreadWorkThread.cpp

    #include "movetothreadworkthread.h"
    #include <QProcess>
    
    moveToThreadWorkThread::moveToThreadWorkThread(QObject *parent,QString cmd) : QObject(parent),commentStr(cmd)
    {
    
    }
    moveToThreadWorkThread::~moveToThreadWorkThread()
    {
    }
    void moveToThreadWorkThread::start1()
    {
        emit workStart();
        doWork();
    }
    void moveToThreadWorkThread::doWork()
    {
        int res=QProcess::execute(commentStr.toStdString().c_str());
        // 准备更新
        emit resultReady(commentStr);
        emit workFinished();
    
    }
    
    

    线程开始

        QThread* m_workerThread = new QThread();
        moveToThreadWorkThread* worker = new moveToThreadWorkThread(nullptr,cmdXml); //第一个参数填nullptr,如果把对象通过 moveToThread 移动到其他线程,这个对象不能有父对象
        worker->moveToThread(m_workerThread);
    
        connect(m_workerThread, &QThread::started, worker, &moveToThreadWorkThread::start1);
        connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
        connect(worker, &moveToThreadWorkThread::workFinished, worker, &moveToThreadWorkThread::deleteLater);
        connect(worker, &moveToThreadWorkThread::workFinished, m_workerThread, &QThread::quit);
        connect(m_workerThread, &QThread::finished, m_workerThread, &QThread::deleteLater);
        m_workerThread->start();
    

    线程执行结束响应

    // 线程执行返回
    void MainWindow::handleResults(QString cmd)
    {
       // qDebug() << "Handle Thread : " << QThread::currentThreadId();
    
       statusProgressBar->hide() ;    //隐藏状态栏进度条
        .....
    }
    
  • 相关阅读:
    Python字符串
    ListCtrl控件
    leetcode1004
    leetcode1003
    leetcode1002
    leetcode153
    leetcode540
    leetcode435
    leetcode999
    leetcode997
  • 原文地址:https://www.cnblogs.com/pozhu15/p/13285891.html
Copyright © 2011-2022 走看看