【QT常用技术讲解】多线程编程处理卡顿

前言

本文在上一篇【QT常用技术讲解】tableWidget右键菜单及多进程编程的基础上,加入多线程,解决调用进程执行后台命令导致QT程序卡顿的现象。

概述

QT应用本身是一个进程,当通过QProcess创建一个进程来执行其他任务时,QT应用是被阻塞的,必须等待QProcess创建的进程执行完,才能继续往下执行,这是典型的进程阻塞模式。而使用多线程,则是"并行执行"的效果,此时QT应用就不会有卡顿现象,多线程是QT项目处理卡顿现象最常用的方法。

功能讲解

增加通用的执行后台命令的线程类,下面为threadCmd.h的源码:

复制代码
#ifndef THREADCMD_H
#define THREADCMD_H

#include <QThread>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QString>
#include "src/util/comm_define.h"

class ThreadCmd : public QThread
{
    Q_OBJECT
public:
    explicit ThreadCmd(const QString &param,QObject *parent = nullptr) ;

protected:
    void run() override;
signals:
    void callback(const QString result);

private:
    QString m_param;
};

#endif // THREADCMD_H

以下为threadCmd.cpp的源码:

复制代码
#ifndef THREADCMD_CPP
#define THREADCMD_CPP

#include "threadCmd.h"
#include <QDebug>
#include <QProcess>
#include "src/util/comm_define.h"
#include <QTextCodec>

ThreadCmd::ThreadCmd(const QString &param,QObject *parent) : QThread(parent),m_param(param) {

}

void ThreadCmd::run(){
    QProcess process;
    // 执行命令
    QString cmd = m_param;
    qDebug() << __LINE__ << cmd;
    process.start(cmd);
    if(process.waitForFinished()){
        // 读取进程的输出
        QString output = QString::fromLocal8Bit(process.readAllStandardOutput());
        QTextCodec *codec = QTextCodec::codecForName("GBK");
        QString unicodeOutput = codec->toUnicode(output.toLocal8Bit());
        emit callback(unicodeOutput);
    }else{
        emit callback("[error]:命令执行失败");
    }
    // 进程使用完毕后,可以手动删除
    process.deleteLater();
}


#endif // THREADCMD_CPP

ping对话框涉及的改动点,pingdialog.h调整代码如下

复制代码
private slots: 
    void ThreadsendResult(const QString &result);//执行后台命令的槽函数
    void ThreadkillProc(const QString &result);//执行kill进程的槽函数

pingdialog.cpp调整代码如下

复制代码
void pingDialog::on_start_clicked()
{
    ui->textBrowser->setReadOnly(false);//
    ui->textBrowser->setText("--------ping start--------");
    QString times = ui->timeBox->currentText();
    QString Ipstr=ui->ipEdit->text();
    QString cmd = QString("ping -n %1 %2").arg(times).arg(Ipstr);

    m_isStart=true;
    //把调用QProcess执行后台命令的代码改成调用多线程类
    ThreadCmd *thread = new ThreadCmd(cmd, this);
    //等待多线程的callback信号,关联ThreadsendResult槽函数来处理结果
    connect(thread, &ThreadCmd::callback, this, &pingDialog::ThreadsendResult);
    thread->start();

}


void pingDialog::on_stop_clicked()
{
    if(m_isStart==true){
        ui->textBrowser->setReadOnly(false);//
        ui->textBrowser->setText("--------ping stop--------");
        //QString cmd = QString("pkill ping");//linux执行的
        QString cmd = QString("taskkill /IM ping.exe /F");

        ThreadCmd *thread = new ThreadCmd(cmd, this);
        connect(thread, &ThreadCmd::callback, this, &pingDialog::ThreadkillProc);
        thread->start();
    }
}

void pingDialog::ThreadsendResult(const QString &result)
{
    qDebug() << "ThreadsendResult finished with result:" << result;
    ui->textBrowser->append(result);
    ThreadCmd *thread = qobject_cast<ThreadCmd *>(sender());
    if (thread) {
        thread->deleteLater(); // 删除线程对象
    }
    m_isStart=false;
}

void pingDialog::ThreadkillProc(const QString &result)
{
    qDebug() << "ThreadkillProc finished with result:" << result;
    ThreadCmd *thread = qobject_cast<ThreadCmd *>(sender());
    if (thread) {
        thread->deleteLater(); // 删除线程对象
    }
}

注意事项

并非所有的事务都要开线程来处理,QT本身已经有很好的机制来处理前端互动的效果了。开了线程一定有损耗(创建、回收等),必定会影响性能,做为C/C++开发者,写代码必须得考虑性能的因素。

而阻塞模式对性能的影响很大,远远超出线程的消耗,常见的阻塞方式有:

1、通过进程打开"第三方"应用;

2、网络编程的等待及响应;

相关推荐
Bony-1 小时前
Go语言完全学习指南 - 从基础到精通------语言基础篇
服务器·开发语言·golang
fl1768312 小时前
基于python的天气预报系统设计和可视化数据分析源码+报告
开发语言·python·数据分析
ACP广源盛139246256732 小时前
(ACP广源盛)GSV6172---MIPI/LVDS 信号转换为 Type-C/DisplayPort 1.4/HDMI 2.0 并集成嵌入式 MCU
c语言·开发语言·单片机·嵌入式硬件·音视频
不穿格子的程序员3 小时前
从零开始刷算法-栈-括号匹配
java·开发语言·
Tony小周3 小时前
使用QKeyEvent keyPress(QEvent::KeyPress, key模拟键盘发送事件,会导致主程序卡死
嵌入式硬件·qt
雪域迷影3 小时前
C#中通过get请求获取api.open-meteo.com网站的天气数据
开发语言·http·c#·get
yue0083 小时前
C#类继承
java·开发语言·c#
Want5953 小时前
Python汤姆猫
开发语言·python
Larry_Yanan3 小时前
QML学习笔记(五十)QML与C++交互:QML中单例C++对象
开发语言·c++·笔记·qt·学习·ui·交互
凯芸呢3 小时前
Java中的数组(续)
java·开发语言·数据结构·算法·青少年编程·排序算法·idea