Qt5中創建臨時的後臺線程。
阿新 • • 發佈:2017-09-30
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_OBJECT7 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中創建臨時的後臺線程。