Qt5中创建临时的后台线程。

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

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

 

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

 1 #include <QObject>
 2 #include <QStringList>
 3 
 4 class ZipUpdatePackageTask : public QObject
 5 {
 6     Q_OBJECT
 7 
 8 public:
 9     ZipUpdatePackageTask();
10     ~ZipUpdatePackageTask();
11 
12 public slots:
13     void doZip();
14     void beZipFiles(const QStringList& files);
15 signals:
16     void zipFinished();
17     void zipPackageInfo(const QString& fileName, const QString& md5, const QString& size);
18 
19 private:
20     bool beZipFilesIsEmpty();
21     void deleteHistoryZip(const QString& targetPackage);
22     void toBeZipFilesArguments(QString &files);
23     void startZipTask(QString zipExePath, QString targetPackage, QString files);
24     QString getFileMD5(const QString& targetZipPackage);
25     QString getFileSize(const QString& targetZipPackage);
26 private:
27     QStringList m_files;
28 };

 

压缩任务类的 cpp文件:

  1 #include <QCoreApplication>
  2 #include <QFile>
  3 #include <QFileInfo>
  4 #include <QDir>
  5 #include <QProcess>
  6 #include <QCryptographicHash>
  7 
  8 ZipUpdatePackageTask::ZipUpdatePackageTask()
  9 {
 10 }
 11 
 12 ZipUpdatePackageTask::~ZipUpdatePackageTask()
 13 {
 14 }
 15 
 16 void ZipUpdatePackageTask::doZip()
 17 {
 18     QString appDir = qApp->applicationDirPath();
 19     QString zipExePath = QString("%1/%2").arg(appDir).arg("zip.exe");
 20     if (QFile::exists(zipExePath) && !beZipFilesIsEmpty())
 21     {
 22 
 23         QString targetZipPackage = QString("%1/%2").arg(appDir).arg("update.zip");
 24         QString beZipFiles;
 25 
 26         toBeZipFilesArguments(beZipFiles);
 27         deleteHistoryZip(targetZipPackage);
 28         startZipTask(zipExePath, targetZipPackage, beZipFiles);
 29 
 30 
 31         if (QFile::exists(targetZipPackage))
 32         {
 33             QString size = getFileSize(targetZipPackage);
 34             QString md5 = getFileMD5(targetZipPackage);
 35 
 36             emit zipPackageInfo(targetZipPackage, md5, size);
 37 
 38         }
 39 
 40 
 41     }
 42 
 43     emit zipFinished();
 44 }
 45 
 46 void ZipUpdatePackageTask::beZipFiles(const QStringList& files)
 47 {
 48     m_files.clear();
 49     m_files = files;
 50 }
 51 
 52 bool ZipUpdatePackageTask::beZipFilesIsEmpty()
 53 {
 54     return m_files.isEmpty();
 55 }
 56 
 57 void ZipUpdatePackageTask::deleteHistoryZip(const QString& targetPackage)
 58 {
 59     if (QFile::exists(targetPackage))
 60     {
 61         QDir dir;
 62         dir.remove(targetPackage);
 63     }
 64 }
 65 
 66 void ZipUpdatePackageTask::toBeZipFilesArguments(QString &files)
 67 {
 68     for (auto file : m_files)
 69     {
 70         files.append(file);
 71         files.append(" ");
 72     }
 73 }
 74 
 75 void ZipUpdatePackageTask::startZipTask(QString zipExePath, QString targetPackage, QString files)
 76 {
 77     QProcess* zipProcesss = new QProcess;
 78     //zip a [zip_package_path_name] [file1Path]...[fileNPath]
 79     QString command = QString("%1 a %2 %3").arg(zipExePath).arg(targetPackage).arg(files);
 80     zipProcesss->start(command);
 81     zipProcesss->waitForFinished(-1);
 82 }
 83 
 84 QString ZipUpdatePackageTask::getFileMD5(const QString& targetZipPackage)
 85 {
 86     QString md5;
 87     QFile file(targetZipPackage);
 88     if (file.open(QFile::ReadOnly))
 89     {
 90         QCryptographicHash hash(QCryptographicHash::Md5);
 91         if (hash.addData(&file))
 92         {
 93             md5 = QString(hash.result().toHex());
 94         }
 95 
 96         file.close();
 97     }
 98     return md5;
 99 }
100 
101 QString ZipUpdatePackageTask::getFileSize(const QString& targetZipPackage)
102 {
103     QFileInfo fileInf(targetZipPackage);
104     return QString::number(fileInf.size());
105 }

 

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

 1 void StatisticsWidget::slotUploadPackage()
 2 {
 3     QThread *zipThread = new QThread;
 4     ZipUpdatePackageTask* task = new ZipUpdatePackageTask();
 5 
 6 
 7     QStringList beZipFiles;
 8     for (int listRow = 0; listRow < ui->updateFileList->count(); ++listRow)
 9     {
10         beZipFiles << ui->updateFileList->item(listRow)->text();
11     }
12 
13     task->beZipFiles(beZipFiles);
14     task->moveToThread(zipThread);
15 
16     connect(zipThread, &QThread::started, task, &ZipUpdatePackageTask::doZip);
17 
18     connect(task, SIGNAL(zipFinished()), zipThread, SLOT(quit()));
19     connect(task, &ZipUpdatePackageTask::zipPackageInfo, this, &StatisticsWidget::slotZipFinished,Qt::QueuedConnection);
20 
21     //automatically delete thread and task object when work is done:
22     connect(zipThread, SIGNAL(finished()), task, SLOT(deleteLater()));
23     connect(zipThread, SIGNAL(finished()), zipThread, SLOT(deleteLater()));
24     zipThread->start();
25 }

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

posted @ 2017-09-30 15:17  foo__hack  阅读(2575)  评论(0编辑  收藏  举报