而不是从中获取价值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);
};
Connect check_sequential_completed
到您需要的地方。
connect(Gen, &HashGen::check_sequential_completed, this, &MafiaDEDLFox::AfterHash);
当然,你不必让未来的观察者成为一次性的。如果你发现每次创建新对象效率低下,你可以将其保留为成员HashGen
.
Note:除了传递 3 个 int 参数之外,还可以发送std::tuple<int, int, int>
。您必须为排队连接注册元类型,这是线程间连接中使用的连接类型。
Q_DECLARE_METATYPE(std::tuple<int, int, int>);
qRegisterMetaType<std::tuple<int, int, int>>();
Edit1:
QFutureWatcher<std::tuple<int,int,int>>
取而代之QFutureWatcher<void>
,无需在此解决方案中存储结果。
Edit2:添加连接等待异步计算完成,当HashGen
物体被摧毁。因此线程不会继续在死亡对象上运行。但它会阻塞主线程一段时间HashGen
被毁了。实际上这就是使用的全部意义QFutureWatcher
,否则如果你确定销毁时不会有异步计算HashGen
对象,无需使用QFutureWatcher
. Just QtConcurrent::run
就足够了。
仅使用 QtConcurrent::run 的示例
以下代码片段来自实际工作项目。
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)));