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() ;    //隐藏状态栏进度条
    .....
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值