zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Qt5中创建临时的后台线程

后台线程 创建 临时 QT5
2023-09-14 09:05:27 时间

开发中有个需求就是,GUI图形界面在上传文件到服务器的时候,需要用zip命令行打包,因为文件很多的时候,zip命令打包需要计算很长时间,所以把这样计算量大的任务分离到后台线程比较合适,然后任务完成,以信号槽机制来通知前台

UI线程处理结果。所以这个线程是需要销毁的,跟之前的一直在运行的后台线程接收网络数据的不一样。

压缩文件的任务类 H文件:


#include 
#include 

class ZipUpdatePackageTask : public QObject
{
    Q_OBJECT

public:
    ZipUpdatePackageTask();
    ~ZipUpdatePackageTask();

public slots:
    void doZip();
    void beZipFiles(const QStringList& files);
signals:
    void zipFinished();
    void zipPackageInfo(const QString& fileName, const QString& md5, const QString& size);

private:
    bool beZipFilesIsEmpty();
    void deleteHistoryZip(const QString& targetPackage);
    void toBeZipFilesArguments(QString &files);
    void startZipTask(QString zipExePath, QString targetPackage, QString files);
    QString getFileMD5(const QString& targetZipPackage);
    QString getFileSize(const QString& targetZipPackage);
private:
    QStringList m_files;
};

压缩任务类的 cpp文件:


#include 
#include 
#include 
#include 
#include 
#include 

ZipUpdatePackageTask::ZipUpdatePackageTask()
{
}

ZipUpdatePackageTask::~ZipUpdatePackageTask()
{
}

void ZipUpdatePackageTask::doZip()
{
    QString appDir = qApp->applicationDirPath();
    QString zipExePath = QString("%1/%2").arg(appDir).arg("zip.exe");
    if (QFile::exists(zipExePath) && !beZipFilesIsEmpty())
    {

        QString targetZipPackage = QString("%1/%2").arg(appDir).arg("update.zip");
        QString beZipFiles;

        toBeZipFilesArguments(beZipFiles);
        deleteHistoryZip(targetZipPackage);
        startZipTask(zipExePath, targetZipPackage, beZipFiles);


        if (QFile::exists(targetZipPackage))
        {
            QString size = getFileSize(targetZipPackage);
            QString md5 = getFileMD5(targetZipPackage);

            emit zipPackageInfo(targetZipPackage, md5, size);

        }


    }

    emit zipFinished();
}

void ZipUpdatePackageTask::beZipFiles(const QStringList& files)
{
    m_files.clear();
    m_files = files;
}

bool ZipUpdatePackageTask::beZipFilesIsEmpty()
{
    return m_files.isEmpty();
}

void ZipUpdatePackageTask::deleteHistoryZip(const QString& targetPackage)
{
    if (QFile::exists(targetPackage))
    {
        QDir dir;
        dir.remove(targetPackage);
    }
}

void ZipUpdatePackageTask::toBeZipFilesArguments(QString &files)
{
    for (auto file : m_files)
    {
        files.append(file);
        files.append(" ");
    }
}

void ZipUpdatePackageTask::startZipTask(QString zipExePath, QString targetPackage, QString files)
{
    QProcess* zipProcesss = new QProcess;
    //zip a [zip_package_path_name] [file1Path]...[fileNPath]
    QString command = QString("%1 a %2 %3").arg(zipExePath).arg(targetPackage).arg(files);
    zipProcesss->start(command);
    zipProcesss->waitForFinished(-1);
}

QString ZipUpdatePackageTask::getFileMD5(const QString& targetZipPackage)
{
    QString md5;
    QFile file(targetZipPackage);
    if (file.open(QFile::ReadOnly))
    {
        QCryptographicHash hash(QCryptographicHash::Md5);
        if (hash.addData(&file))
        {
            md5 = QString(hash.result().toHex());
        }

        file.close();
    }
    return md5;
}

QString ZipUpdatePackageTask::getFileSize(const QString& targetZipPackage)
{
    QFileInfo fileInf(targetZipPackage);
    return QString::number(fileInf.size());
}

以下是创建这个后台压缩线程的槽函数,当压缩上传的button点击,就调用以下这个槽函数:


void StatisticsWidget::slotUploadPackage()
{
    QThread *zipThread = new QThread;
    ZipUpdatePackageTask* task = new ZipUpdatePackageTask();


    QStringList beZipFiles;
    for (int listRow = 0; listRow < ui->updateFileList->count(); ++listRow)
    {
        beZipFiles << ui->updateFileList->item(listRow)->text();
    }

    task->beZipFiles(beZipFiles);
    task->moveToThread(zipThread);

    connect(zipThread, &QThread::started, task, &ZipUpdatePackageTask::doZip);

    connect(task, SIGNAL(zipFinished()), zipThread, SLOT(quit()));
    connect(task, &ZipUpdatePackageTask::zipPackageInfo, this, &StatisticsWidget::slotZipFinished,Qt::QueuedConnection);

    //automatically delete thread and task object when work is done:
    connect(zipThread, SIGNAL(finished()), task, SLOT(deleteLater()));
    connect(zipThread, SIGNAL(finished()), zipThread, SLOT(deleteLater()));
    zipThread->start();
}

注意,以上代码都是临时任务和线程,当任务完成以后,由于设置了相应的信号槽,会自动删除。任务线程做完该做的事儿,发出了一个zipPackageInfo的信号就销毁了。UI线程只用编写一个槽函数来接收做完的信号并处理就可以了。

本文福利, 免费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓