尝试获取文件的 MD5 时 Qt 程序冻结
Qt Program freeze when try to get MD5 of files
您好,我正在使用此代码在 QT 中生成文件的 MD5
QString Md5_gen(QString const &s)
{
QString pakchunk_Md5;
QCryptographicHash crypto(QCryptographicHash::Md5);
QFile pakchunk("D:/Games/TDPA - Man of Medan" + s);
if (pakchunk.open(QIODevice::ReadOnly))
{
while(!pakchunk.atEnd()){
crypto.addData(pakchunk.read(8192));
}
} else
{
qDebug() << "Can't open file.";
pakchunk_Md5 = "nofile";
return pakchunk_Md5;
}
pakchunk_Md5 = crypto.result().toHex();
return pakchunk_Md5;
}
我需要使用此代码生成 8 个大文件的 MD5 (1.5GB>) 问题是当我按下按钮开始生成 MD5 时,GUI 冻结直到所有MD5生成
我以这种方式测试 QFuture, QFutureWatcher, QtConcurrent, 但运气不好,GUI 仍然每次都卡住
main.cpp
#include "user_def.h"
#include "mainwindow2.h"
#include...
QString Md5_gen(QString const &s)
{
QString pakchunk_Md5;
QCryptographicHash crypto(QCryptographicHash::Md5);
QFile pakchunk("D:/Games/TDPA - Man of Medan" + s);
if (pakchunk.open(QIODevice::ReadOnly))
{
while(!pakchunk.atEnd()){
crypto.addData(pakchunk.read(8192));
}
} else
{
qDebug() << "Can't open file.";
pakchunk_Md5 = "nofile";
return pakchunk_Md5;
}
pakchunk_Md5 = crypto.result().toHex();
return pakchunk_Md5;
}
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
a.setStyle(new DarkStyle);
FramelessWindow framelessWindow;
framelessWindow.setWindowIcon(a.style()->standardIcon(QStyle::SP_DesktopIcon));
MainWindow *mainWindow = new MainWindow;
framelessWindow.setContent(mainWindow);
framelessWindow.show();
return a.exec();
}
user_def.h
#ifndef USER_DEF_H
#define USER_DEF_H
#include <QString>
QString Md5_gen(QString const &s);
#endif // USER_DEF_H
mainwindow2.h
#ifndef MAINWINDOW2_H
#define MAINWINDOW2_H
#include <QMainWindow>
#include <QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>
#include <QThread>
#include <QThreadPool>
#include "user_def.h"
namespace Ui {
class MainWindow2;
}
class MainWindow2 : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow2(QWidget *parent = nullptr);
~MainWindow2();
public slots:
void run_thread();
void displayFinishedBox();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow2 *ui;
QFutureWatcher<QString> *watcher;
QFuture<QString> *future;
};
#endif // MAINWINDOW2_H
mainwindow2.cpp
#include...
MainWindow2::MainWindow2(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow2)
{
ui->setupUi(this);
connect(ui->pushButton, &QPushButton::clicked,
this, &MainWindow2::run_thread);
// display a message box when the calculation has finished
future = new QFuture<QString>;
watcher = new QFutureWatcher<QString>;
connect(watcher, SIGNAL(finished()),
this, SLOT(displayFinishedBox()));
}
MainWindow2::~MainWindow2()
{
delete ui;
}
void MainWindow2::run_thread()
{
int file_ok = 0;
//file pak33
QString loc33 = "/SM/test1.pak";
QFuture<QString> future33 = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc33);
watcher->setFuture(future33);
QString pakchunk33 = future33.result();
qDebug() << pakchunk33;
if (pakchunk33 == "f7002d4419cd235a87746715ba6fb2ea")
{
qDebug() << "OK";
file_ok++;
ui->label_8->setText("OK");
ui->label_8->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk33 == "nofile")
{
qDebug() << "no file found";
ui->label_8->setText("not found");
ui->label_8->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_8->setText("wrong");
ui->label_8->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(12);
//file pak34
QString loc34 = "/SM/test2.pak";
QFuture<QString> future34 = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc34);
watcher->setFuture(future34);
QString pakchunk34 = future34.result();
qDebug() << pakchunk34;
if (pakchunk34 == "64c77598586b6c3cb60beed0b0750620")
{
qDebug() << "OK";
file_ok++;
ui->label->setText("OK");
ui->label->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk34 == "nofile")
{
qDebug() << "no file found";
ui->label->setText("not found");
ui->label->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label->setText("wrong");
ui->label->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(25);
//file pak35
QString loc35 = "/SM/test3.pak";
QFuture<QString> future35 = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc35);
watcher->setFuture(future35);
QString pakchunk35 = future35.result();
qDebug() << pakchunk35;
if (pakchunk35 == "ee53f7a7656a32b5278c460baec46f16")
{
qDebug() << "OK";
file_ok++;
ui->label_7->setText("OK");
ui->label_7->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk35 == "nofile")
{
qDebug() << "no file found";
ui->label_7->setText("not found");
ui->label_7->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_7->setText("wrong");
ui->label_7->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(38);
/*Some other code*/
谁能告诉我我的问题是什么,我该如何解决?
编辑 1
我用这种方式编辑我的代码
它在没有冻结 gui 的情况下工作良好
在编码方面,这段代码是标准的吗?
mainwindow2.cpp
MainWindow2::MainWindow2(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow2)
{
ui->setupUi(this);
connect(ui->pushButton_3, &QPushButton::clicked, this, &MainWindow2::MD5_thread_1);
future = new QFuture<QString>;
watcher1 = new QFutureWatcher<QString>;
watcher2 = new QFutureWatcher<QString>;
watcher3 = new QFutureWatcher<QString>;
connect(watcher1, &QFutureWatcher<QString>::finished, this, &MainWindow2::MD5_thread_2);
connect(watcher2, &QFutureWatcher<QString>::finished, this, &MainWindow2::MD5_thread_3);
connect(watcher3, &QFutureWatcher<QString>::finished, this, &MainWindow2::MD5_thread_4);
//some other code
}
void MainWindow2::MD5_thread_1()
{
ui->pushButton->setEnabled(false);
ui->pushButton->setText("procces started");
ui->pushButton->setStyleSheet("QPushButton { color : white; background-color: rgb(73, 80, 93); }");
ui->label->setText("checking");
ui->label_2->setText("checking");
ui->label_3->setText("checking");
ui->label_4->setText("checking");
ui->label_5->setText("checking");
ui->label_6->setText("checking");
ui->label_7->setText("checking");
ui->label_8->setText("checking");
ui->label_14->setText("waiting for end of check");
ui->progressBar->setRange(0, 100);
ui->progressBar_2->setRange(0, 100);
ui->progressBar->setValue(0);
ui->progressBar_2->setValue(0);
//file pak33
QString loc33 = "/SMG0/editor.pak";
*future= QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc33);
watcher1->setFuture(*future);
}
void MainWindow2::MD5_thread_2()
{
QString pakchunk33 = future->result();
qDebug() << pakchunk33;
if (pakchunk33 == "f7002d4419cd235a87746715ba6fb2ea")
{
qDebug() << "OK";
file_ok++;
ui->label_8->setText("OK");
ui->label_8->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk33 == "nofile")
{
qDebug() << "no file found";
ui->label_8->setText("not found");
ui->label_8->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_8->setText("wrong");
ui->label_8->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(12);
watcher1->deleteLater();
//file pak34
QString loc34 = "/SMG0/2Editor.pak";
*future = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc34);
watcher2->setFuture(*future);
}
void MainWindow2::MD5_thread_3()
{
QString pakchunk34 = future->result();
qDebug() << pakchunk34;
if (pakchunk34 == "64c77598586b6c3cb60beed0b0750620")
{
qDebug() << "OK";
file_ok++;
ui->label->setText("OK");
ui->label->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk34 == "nofile")
{
qDebug() << "no file found";
ui->label->setText("not found");
ui->label->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label->setText("wrong");
ui->label->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(25);
watcher2->deleteLater();
//file pak35
QString loc35 = "/SMG0/3Editor.pak";
*future = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc35);
watcher3->setFuture(*future);
}
void MainWindow2::core_install
{
QString pakchunk35 = future->result();
qDebug() << pakchunk40;
if (pakchunk40 == "49e0440340044f424caeb82bade1301f")
{
qDebug() << "OK";
file_ok++;
ui->label_2->setText("OK");
ui->label_2->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk40 == "nofile")
{
qDebug() << "no file found";
ui->label_2->setText("not found");
ui->label_2->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_2->setText("wrong");
ui->label_2->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(100);
watcher3->deleteLater();
//check if game is okey or not
if (file_ok == 8)
{
ui->label_14->setText("O");
ui->label_14->setStyleSheet("QLabel { color : green; }");
} else
{
ui->label_14->setText("X");
ui->label_14->setStyleSheet("QLabel { color : red; }");
}
}
mainwindow2.h
#ifndef MAINWINDOW2_H
#define MAINWINDOW2_H
#include <QMainWindow>
#include <QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>
#include <QThread>
#include <QThreadPool>
#include "user_def.h"
namespace Ui {
class MainWindow2;
}
class MainWindow2 : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow2(QWidget *parent = nullptr);
~MainWindow2();
public slots:
void MD5_thread_1();
void MD5_thread_2();
void MD5_thread_3();
void core_install();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_radioButton_2_clicked();
void on_radioButton_4_clicked();
void on_radioButton_3_clicked();
void on_radioButton_clicked();
private:
Ui::MainWindow2 *ui;
QFutureWatcher<QString> *watcher1;
QFutureWatcher<QString> *watcher2;
QFutureWatcher<QString> *watcher3;
QFuture<QString> *future;
int file_ok = 0;
};
#endif // MAINWINDOW2_H
result
方法阻塞了您的 UI 线程,使整个并发/未来舞蹈变得无用。
为每个未来创建一个观察者,link 将其 finished
信号发送给 lambda,将文件名和结果内容传递给 [=39] 上的 onHashCalculated
方法=].在该方法中,您可以检查散列是否与您预定义的散列之一匹配,并更新 UI.
或者,将您当前的 run_thread
函数移动到在单独线程上运行的单独 QObject,并让它发出一个 hashCalculated(name, hash)
信号,您的 mainwindow 订阅使用onHashCalculated
插槽类似于我上面描述的插槽。
这是封装了这两种方法的 HashChecker 代码。
注意将文件名映射到哈希的静态 QMap
,doneFile
链接到 checkDone
的方式。
enum class Status { Ok, NotOk, Missing };
class HashChecker : public QObject {
Q_OBJECT
public:
QMap<QString, Status> done;
HashChecker(QObject *parent = nullptr) : QObject(parent) {
QObject::connect(this, &HashChecker::doneFile, this, &HashChecker::checkDone);
}
inline static const QMap<QString, QString> hashes = {
{"/SM/test1.pak", "f7002d4419cd235a87746715ba6fb2ea"},
{"/SM/test2.pak", "64c77598586b6c3cb60beed0b0750620"},
{"/SM/test3.pak", "ee53f7a7656a32b5278c460baec46f16"},
};
signals:
void finished();
void doneFile(const QString& fname, Status s);
private slots:
void checkDone(const QString& fname, Status s) {
done[fname] = s;
if (done.size() == hashes.size())
emit finished();
}
public slots:
void check_parallel() {
for (auto it = hashes.cbegin(); it != hashes.cend(); it++) {
auto fname = it.key();
auto hash = it.value();
QFuture<Status> fut = QtConcurrent::run(do_hash, fname, hash);
QFutureWatcher<Status> *fw = new QFutureWatcher<Status>(this);
fw->setFuture(fut);
QObject::connect(fw, &QFutureWatcher<Status>::finished, this,
[=]() {
fw->deleteLater();
emit doneFile(fname, fut.result());
});
}
}
void check_sequential() {
for (auto it = hashes.cbegin(); it != hashes.cend(); it++) {
auto fname = it.key();
auto hash = it.value();
auto result = do_hash(fname, hash);
emit doneFile(fname, result);
}
}
};
如果要并行检查文件:
HashChecker *hc = new HashChecker();
QObject::connect(hc, &HashChecker::doneFile, this, &MainWindow2::onHashCalculated);
hc->check_parallel();
不同线程中的顺序几乎是一样的:
QThread *t = new QThread(this);
HashChecker *hc = new HashChecker();
hc->moveToThread(t);
QObject::connect(t, &QThread::started, hc, &HashChecker::check_sequential);
QObject::connect(hc, &HashChecker::doneFile, this, &MainWindow2::onHashCalculated);
QObject::connect(hc, &HashChecker::finished, t, &QThread::quit);
t->start();
您好,我正在使用此代码在 QT 中生成文件的 MD5
QString Md5_gen(QString const &s)
{
QString pakchunk_Md5;
QCryptographicHash crypto(QCryptographicHash::Md5);
QFile pakchunk("D:/Games/TDPA - Man of Medan" + s);
if (pakchunk.open(QIODevice::ReadOnly))
{
while(!pakchunk.atEnd()){
crypto.addData(pakchunk.read(8192));
}
} else
{
qDebug() << "Can't open file.";
pakchunk_Md5 = "nofile";
return pakchunk_Md5;
}
pakchunk_Md5 = crypto.result().toHex();
return pakchunk_Md5;
}
我需要使用此代码生成 8 个大文件的 MD5 (1.5GB>) 问题是当我按下按钮开始生成 MD5 时,GUI 冻结直到所有MD5生成
我以这种方式测试 QFuture, QFutureWatcher, QtConcurrent, 但运气不好,GUI 仍然每次都卡住
main.cpp
#include "user_def.h"
#include "mainwindow2.h"
#include...
QString Md5_gen(QString const &s)
{
QString pakchunk_Md5;
QCryptographicHash crypto(QCryptographicHash::Md5);
QFile pakchunk("D:/Games/TDPA - Man of Medan" + s);
if (pakchunk.open(QIODevice::ReadOnly))
{
while(!pakchunk.atEnd()){
crypto.addData(pakchunk.read(8192));
}
} else
{
qDebug() << "Can't open file.";
pakchunk_Md5 = "nofile";
return pakchunk_Md5;
}
pakchunk_Md5 = crypto.result().toHex();
return pakchunk_Md5;
}
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
a.setStyle(new DarkStyle);
FramelessWindow framelessWindow;
framelessWindow.setWindowIcon(a.style()->standardIcon(QStyle::SP_DesktopIcon));
MainWindow *mainWindow = new MainWindow;
framelessWindow.setContent(mainWindow);
framelessWindow.show();
return a.exec();
}
user_def.h
#ifndef USER_DEF_H
#define USER_DEF_H
#include <QString>
QString Md5_gen(QString const &s);
#endif // USER_DEF_H
mainwindow2.h
#ifndef MAINWINDOW2_H
#define MAINWINDOW2_H
#include <QMainWindow>
#include <QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>
#include <QThread>
#include <QThreadPool>
#include "user_def.h"
namespace Ui {
class MainWindow2;
}
class MainWindow2 : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow2(QWidget *parent = nullptr);
~MainWindow2();
public slots:
void run_thread();
void displayFinishedBox();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow2 *ui;
QFutureWatcher<QString> *watcher;
QFuture<QString> *future;
};
#endif // MAINWINDOW2_H
mainwindow2.cpp
#include...
MainWindow2::MainWindow2(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow2)
{
ui->setupUi(this);
connect(ui->pushButton, &QPushButton::clicked,
this, &MainWindow2::run_thread);
// display a message box when the calculation has finished
future = new QFuture<QString>;
watcher = new QFutureWatcher<QString>;
connect(watcher, SIGNAL(finished()),
this, SLOT(displayFinishedBox()));
}
MainWindow2::~MainWindow2()
{
delete ui;
}
void MainWindow2::run_thread()
{
int file_ok = 0;
//file pak33
QString loc33 = "/SM/test1.pak";
QFuture<QString> future33 = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc33);
watcher->setFuture(future33);
QString pakchunk33 = future33.result();
qDebug() << pakchunk33;
if (pakchunk33 == "f7002d4419cd235a87746715ba6fb2ea")
{
qDebug() << "OK";
file_ok++;
ui->label_8->setText("OK");
ui->label_8->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk33 == "nofile")
{
qDebug() << "no file found";
ui->label_8->setText("not found");
ui->label_8->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_8->setText("wrong");
ui->label_8->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(12);
//file pak34
QString loc34 = "/SM/test2.pak";
QFuture<QString> future34 = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc34);
watcher->setFuture(future34);
QString pakchunk34 = future34.result();
qDebug() << pakchunk34;
if (pakchunk34 == "64c77598586b6c3cb60beed0b0750620")
{
qDebug() << "OK";
file_ok++;
ui->label->setText("OK");
ui->label->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk34 == "nofile")
{
qDebug() << "no file found";
ui->label->setText("not found");
ui->label->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label->setText("wrong");
ui->label->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(25);
//file pak35
QString loc35 = "/SM/test3.pak";
QFuture<QString> future35 = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc35);
watcher->setFuture(future35);
QString pakchunk35 = future35.result();
qDebug() << pakchunk35;
if (pakchunk35 == "ee53f7a7656a32b5278c460baec46f16")
{
qDebug() << "OK";
file_ok++;
ui->label_7->setText("OK");
ui->label_7->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk35 == "nofile")
{
qDebug() << "no file found";
ui->label_7->setText("not found");
ui->label_7->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_7->setText("wrong");
ui->label_7->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(38);
/*Some other code*/
谁能告诉我我的问题是什么,我该如何解决?
编辑 1
我用这种方式编辑我的代码 它在没有冻结 gui 的情况下工作良好 在编码方面,这段代码是标准的吗?
mainwindow2.cpp
MainWindow2::MainWindow2(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow2)
{
ui->setupUi(this);
connect(ui->pushButton_3, &QPushButton::clicked, this, &MainWindow2::MD5_thread_1);
future = new QFuture<QString>;
watcher1 = new QFutureWatcher<QString>;
watcher2 = new QFutureWatcher<QString>;
watcher3 = new QFutureWatcher<QString>;
connect(watcher1, &QFutureWatcher<QString>::finished, this, &MainWindow2::MD5_thread_2);
connect(watcher2, &QFutureWatcher<QString>::finished, this, &MainWindow2::MD5_thread_3);
connect(watcher3, &QFutureWatcher<QString>::finished, this, &MainWindow2::MD5_thread_4);
//some other code
}
void MainWindow2::MD5_thread_1()
{
ui->pushButton->setEnabled(false);
ui->pushButton->setText("procces started");
ui->pushButton->setStyleSheet("QPushButton { color : white; background-color: rgb(73, 80, 93); }");
ui->label->setText("checking");
ui->label_2->setText("checking");
ui->label_3->setText("checking");
ui->label_4->setText("checking");
ui->label_5->setText("checking");
ui->label_6->setText("checking");
ui->label_7->setText("checking");
ui->label_8->setText("checking");
ui->label_14->setText("waiting for end of check");
ui->progressBar->setRange(0, 100);
ui->progressBar_2->setRange(0, 100);
ui->progressBar->setValue(0);
ui->progressBar_2->setValue(0);
//file pak33
QString loc33 = "/SMG0/editor.pak";
*future= QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc33);
watcher1->setFuture(*future);
}
void MainWindow2::MD5_thread_2()
{
QString pakchunk33 = future->result();
qDebug() << pakchunk33;
if (pakchunk33 == "f7002d4419cd235a87746715ba6fb2ea")
{
qDebug() << "OK";
file_ok++;
ui->label_8->setText("OK");
ui->label_8->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk33 == "nofile")
{
qDebug() << "no file found";
ui->label_8->setText("not found");
ui->label_8->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_8->setText("wrong");
ui->label_8->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(12);
watcher1->deleteLater();
//file pak34
QString loc34 = "/SMG0/2Editor.pak";
*future = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc34);
watcher2->setFuture(*future);
}
void MainWindow2::MD5_thread_3()
{
QString pakchunk34 = future->result();
qDebug() << pakchunk34;
if (pakchunk34 == "64c77598586b6c3cb60beed0b0750620")
{
qDebug() << "OK";
file_ok++;
ui->label->setText("OK");
ui->label->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk34 == "nofile")
{
qDebug() << "no file found";
ui->label->setText("not found");
ui->label->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label->setText("wrong");
ui->label->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(25);
watcher2->deleteLater();
//file pak35
QString loc35 = "/SMG0/3Editor.pak";
*future = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc35);
watcher3->setFuture(*future);
}
void MainWindow2::core_install
{
QString pakchunk35 = future->result();
qDebug() << pakchunk40;
if (pakchunk40 == "49e0440340044f424caeb82bade1301f")
{
qDebug() << "OK";
file_ok++;
ui->label_2->setText("OK");
ui->label_2->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk40 == "nofile")
{
qDebug() << "no file found";
ui->label_2->setText("not found");
ui->label_2->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_2->setText("wrong");
ui->label_2->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(100);
watcher3->deleteLater();
//check if game is okey or not
if (file_ok == 8)
{
ui->label_14->setText("O");
ui->label_14->setStyleSheet("QLabel { color : green; }");
} else
{
ui->label_14->setText("X");
ui->label_14->setStyleSheet("QLabel { color : red; }");
}
}
mainwindow2.h
#ifndef MAINWINDOW2_H
#define MAINWINDOW2_H
#include <QMainWindow>
#include <QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>
#include <QThread>
#include <QThreadPool>
#include "user_def.h"
namespace Ui {
class MainWindow2;
}
class MainWindow2 : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow2(QWidget *parent = nullptr);
~MainWindow2();
public slots:
void MD5_thread_1();
void MD5_thread_2();
void MD5_thread_3();
void core_install();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_radioButton_2_clicked();
void on_radioButton_4_clicked();
void on_radioButton_3_clicked();
void on_radioButton_clicked();
private:
Ui::MainWindow2 *ui;
QFutureWatcher<QString> *watcher1;
QFutureWatcher<QString> *watcher2;
QFutureWatcher<QString> *watcher3;
QFuture<QString> *future;
int file_ok = 0;
};
#endif // MAINWINDOW2_H
result
方法阻塞了您的 UI 线程,使整个并发/未来舞蹈变得无用。
为每个未来创建一个观察者,link 将其 finished
信号发送给 lambda,将文件名和结果内容传递给 [=39] 上的 onHashCalculated
方法=].在该方法中,您可以检查散列是否与您预定义的散列之一匹配,并更新 UI.
或者,将您当前的 run_thread
函数移动到在单独线程上运行的单独 QObject,并让它发出一个 hashCalculated(name, hash)
信号,您的 mainwindow 订阅使用onHashCalculated
插槽类似于我上面描述的插槽。
这是封装了这两种方法的 HashChecker 代码。
注意将文件名映射到哈希的静态 QMap
,doneFile
链接到 checkDone
的方式。
enum class Status { Ok, NotOk, Missing };
class HashChecker : public QObject {
Q_OBJECT
public:
QMap<QString, Status> done;
HashChecker(QObject *parent = nullptr) : QObject(parent) {
QObject::connect(this, &HashChecker::doneFile, this, &HashChecker::checkDone);
}
inline static const QMap<QString, QString> hashes = {
{"/SM/test1.pak", "f7002d4419cd235a87746715ba6fb2ea"},
{"/SM/test2.pak", "64c77598586b6c3cb60beed0b0750620"},
{"/SM/test3.pak", "ee53f7a7656a32b5278c460baec46f16"},
};
signals:
void finished();
void doneFile(const QString& fname, Status s);
private slots:
void checkDone(const QString& fname, Status s) {
done[fname] = s;
if (done.size() == hashes.size())
emit finished();
}
public slots:
void check_parallel() {
for (auto it = hashes.cbegin(); it != hashes.cend(); it++) {
auto fname = it.key();
auto hash = it.value();
QFuture<Status> fut = QtConcurrent::run(do_hash, fname, hash);
QFutureWatcher<Status> *fw = new QFutureWatcher<Status>(this);
fw->setFuture(fut);
QObject::connect(fw, &QFutureWatcher<Status>::finished, this,
[=]() {
fw->deleteLater();
emit doneFile(fname, fut.result());
});
}
}
void check_sequential() {
for (auto it = hashes.cbegin(); it != hashes.cend(); it++) {
auto fname = it.key();
auto hash = it.value();
auto result = do_hash(fname, hash);
emit doneFile(fname, result);
}
}
};
如果要并行检查文件:
HashChecker *hc = new HashChecker();
QObject::connect(hc, &HashChecker::doneFile, this, &MainWindow2::onHashCalculated);
hc->check_parallel();
不同线程中的顺序几乎是一样的:
QThread *t = new QThread(this);
HashChecker *hc = new HashChecker();
hc->moveToThread(t);
QObject::connect(t, &QThread::started, hc, &HashChecker::check_sequential);
QObject::connect(hc, &HashChecker::doneFile, this, &MainWindow2::onHashCalculated);
QObject::connect(hc, &HashChecker::finished, t, &QThread::quit);
t->start();