C++ 从std::tuple函数QtConcurrentRun获取(多)返回值
嗨,我有一个类用于在Qt中生成某个文件的MD5(我使用tuple从中返回多个值),我想在其他线程上运行它,因为生成所有文件MD5可能需要一些时间,并且它的冻结guiC++ 从std::tuple函数QtConcurrentRun获取(多)返回值,c++,qt,tuples,C++,Qt,Tuples,嗨,我有一个类用于在Qt中生成某个文件的MD5(我使用tuple从中返回多个值),我想在其他线程上运行它,因为生成所有文件MD5可能需要一些时间,并且它的冻结gui 我决定使用QtConcurrentRun在其他线程上运行它,但到目前为止,我不知道如何获取所有元组返回值 这是我的密码 HashGen.h #pragma一次 #包括“stdafx.h” HashGen类:公共QObject { Q_对象 公众: HashGen(QObject*parent=nullptr); 私人: QStrin
我决定使用QtConcurrentRun在其他线程上运行它,但到目前为止,我不知道如何获取所有元组返回值
这是我的密码 HashGen.h
#pragma一次
#包括“stdafx.h”
HashGen类:公共QObject
{
Q_对象
公众:
HashGen(QObject*parent=nullptr);
私人:
QString Md5_gen(QString const&fname);
公众时段:
std::tuple check_sequential();
};
HashGen.cpp
#包括“stdafx.h”
#包括“HashGen.h”
HashGen::HashGen(QObject*父对象)
:QObject(父对象)
{
}
QString HashGen::Md5_gen(QString const&fname)
{
//生成给定文件名的MD5
}
std::tuple HashGen::check_sequential(){
QString文件1[2]={“8C0B1E649207BDC113FAAE3D34FA5C5”,“”;//empty”“稍后用其他MD5哈希值填充
QString文件2[4]={“0547F42982DD9EDB7B47931DF15”、“”、“”、“”、“”};
QString文件3[2]={“57f08e690e2655749291b2da4be8b021”,“”;
QString file1_H=Md5_gen(“/proj/file.zip”);
QString file2_H=Md5_gen(“/proj/file2.zip”);
QString文件3_H=Md5_gen(“/proj/file3.zip”);
int file1_status=0;
int file2_status=0;
int file3_status=0;
对于(int i=0;i<2;i++)
{
if(file1[i]!=“nofile”)
{
if(file1[i]==file1\u H)
{
file1_status=i;
打破
}
else{file1_status=422;}//仅仅是一个随机数意味着文件与任何MD5都不匹配
}
其他的
{
file1_status=404;//只是一个随机数意味着文件不存在
打破
}
}
对于(int i=0;i<4;i++)
{
if(file2[i]!=“nofile”)
{
if(file2[i]==file2\u H)
{
文件2_状态=i;
打破
}
else{file2_status=422;}
}
其他的
{
文件2_状态=404;
打破
}
}
对于(int i=0;i<2;i++)
{
if(file3[i]!=“nofile”)
{
if(file3[i]==file3\u H)
{
file3_status=i;
打破
}
else{file3_status=422;}
}
其他的
{
file3_status=404;
打破
}
}
返回{file1_status,file2_status,file3_status};//返回所有文件状态
main window.cpp
void主窗口::在按钮上点击()
{
QFuture Hash=QtConcurrent::run(Gen,&HashGen::check_sequential);
QFutureWatcher*watcher=新QFutureWatcher;
连接(watcher和QFutureWatcher::finished、this和MafiaDEDLFox::AfterHash);
观察者->设置未来(散列);
}
另一个问题是我需要使用QFuturewatcher来监视QFuture,但我不知道在哪里最好地声明它(所以当函数超出范围时它不会被删除)
如果我不能正确解释我的问题,很抱歉,但我希望有人能帮助我,谢谢你,而不是从
QFutureWatcher
获取价值,你可以通过信号发送。我们可以创建一个一次性的QFutureWatcher
,在工作完成后自动删除
class HashGen : public QObject
{
Q_OBJECT
public:
HashGen(QObject *parent = nullptr);
private:
QString Md5_gen(QString const& fname);
public slots:
std::tuple<int, int, int> check_sequential() {
...
// notify when completed
emit check_sequential_completed(file1_status, file2_status, file3_status);
return { file1_status, file2_status, file3_status}; // Return all file status
}
void async_check_sequential() {
// create future watcher as child
auto futureWatcher = new QFutureWatcher<void>(this);
// kill yourself when you done
connect(futureWatcher, &QFutureWatcher<void>::finished, futureWatcher, &QObject::deleteLater);
// Wait for finish of computation when HashGen about to die
connect(this, &QObject::destroyed, [futureWatcher](){ futureWatcher->waitForFinished(); });
// start check sequential in another thread
futureWatcher.setFuture(QtConcurrent::run(this, &HashGen::check_sequential));
}
signals:
void check_sequential_completed(int, int, int);
};
当然,您不必让future watcher成为一次性的。如果您发现每次创建新对象都效率低下,您可以将其保留为HashGen
的成员
注意:
可以发送std::tuple
,而不是传递3个int-atguments。您必须为排队连接注册元类型,这是线程间连接中使用的连接类型
Q_DECLARE_METATYPE(std::tuple<int, int, int>);
qRegisterMetaType<std::tuple<int, int, int>>();
联系
connect(scanButton, SIGNAL(clicked()), m_invoker, SLOT(asyncScanAddresses()));
connect(m_invoker, SIGNAL(addressListReady(QStringList)), this, SLOT(updateAddressList(QStringList)));
谢谢你的回答,所以你说不需要使用元组函数来返回多个值,而是最好使用一个信号并将所有输出发送到GUI线程中的插槽?只有一个问题,所以你认为没有必要使用
QFuture
和QFutureWatcher
,只需使用qtccurren
t和等待信号发送数据。对吗?@file tracer如果您确定HashGen销毁时没有线程运行,则无需使用QFutureWatcher
。与finished()
或resultradayat()不同
signal,您可以在单个步骤中使用自定义信号获得结果。QFutureWatcher
的某些功能不适用于QtConcurrent::run
,例如cancel()
,因此我认为它对于其他QtConcurrent
函数更具吸引力。谢谢,还有一件事,我想从我的主线程(gui)运行HashGen函数在按下一个按钮后,我不知道为什么我要按你说的做,但是我的程序崩溃了,调试器说这是因为检查\u sequential\u completed
信号…你能从主线程添加一个在新线程中运行函数的示例并再次在主线程中获得它的输出吗?我是qt中的新手,如果你能帮助我,我将不胜感激this@file-trac呃,我刚刚从我的一个项目中添加了一个示例,并对其进行了测试。它运行良好。我不知道为什么您的程序会崩溃。对不起。
class AddPrinterInvoker : public QObject
{
Q_OBJECT
public:
AddPrinterInvoker(QObject* parent = nullptr);
QStringList scanAddresses() {
...
emit addressListReady(addressList);
return addressList;
}
public slots:
void asyncScanAddresses() { QtConcurrent::run(this, &AddPrinterInvoker::scanAddresses); }
signals:
void addressListReady(QStringList addressList);
}
connect(scanButton, SIGNAL(clicked()), m_invoker, SLOT(asyncScanAddresses()));
connect(m_invoker, SIGNAL(addressListReady(QStringList)), this, SLOT(updateAddressList(QStringList)));