1. 程式人生 > >Qt5中創建臨時的後臺線程。

Qt5中創建臨時的後臺線程。

process name targe button move div 計算 info 後臺線程

有個需求就是,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線程只用編寫一個槽函數來接收做完的信號並處理就可以了。

Qt5中創建臨時的後臺線程。