有个需求就是,GUI图形界面在上传文件到服务器的时候,需要用zip命令行打包,因为文件很多的时候,zip命令打包需要计算很长时间,所以把这样计算量大的任务分离到后台线程比较合适,然后任务完成,以信号槽机制来通知前台
UI线程处理结果。所以这个线程是需要销毁的,跟之前的一直在运行的后台线程接收网络数据的不一样。
压缩文件的任务类 H文件:
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文件:
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线程只用编写一个槽函数来接收做完的信号并处理就可以了。
Qt5中创建临时的后台线程。- foo__hack - 博客园 (cnblogs.com)
原文始发于微信公众号(汇编语言):Qt5中创建临时的后台线程。
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论