从 std::tuple 函数 QtConcurrentRun 获取(多)返回值

2024-03-13

您好,我有一个用于在 Qt 中生成某个文件的 MD5 的类(我使用元组从中返回多个值),我想在其他线程上运行它,因为生成所有文件 MD5 可能需要一些时间并且它的冻结 gui
我决定使用Qt并发运行在其他线程上运行它,但到目前为止我对如何获取所有元组返回值没有任何想法
这是我的代码

哈希生成器h

#pragma once

#include "stdafx.h"

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();
};

HashGen.cpp

#include "stdafx.h"
#include "HashGen.h"

HashGen::HashGen(QObject *parent)
    : QObject(parent)
{
}

QString HashGen::Md5_gen(QString const& fname)
{
    //Generate MD5 of giving file name
}

std::tuple<int, int, int> HashGen::check_sequential() {
    QString file1[2] = { "8c0b1e6492078bdc113faae3d34fa5c5", "" }; // empty "" fill with other MD5 hash later
    QString file2[4] = { "0547f42982dd9edb7b47931d00efff15", "", "", "" };
    QString file3[2] = { "57f08e690e2655749291b2da4be8b021", "" };

    QString file1_H = Md5_gen("/proj/file.zip");
    QString file2_H = Md5_gen("/proj/file2.zip");
    QString file3_H = Md5_gen("/proj/file3.zip");

    int file1_status = 0;
    int file2_status = 0;
    int file3_status = 0;

    for (int i = 0; i < 2; i++)
    {
        if (file1[i] != "nofile")
        {
            if (file1[i] == file1_H)
            {
                file1_status = i;
                break;
            }
            else { file1_status = 422; } // Just a random number mean file doesn't match any MD5
        }
        else
        {
            file1_status = 404; // Just a random number mean file doesn't exist
            break;
        }
    }

    for (int i = 0; i < 4; i++)
    {
        if (file2[i] != "nofile")
        {
            if (file2[i] == file2_H)
            {
                file2_status = i;
                break;
            }
            else { file2_status = 422; }
        }
        else
        { 
            file2_status = 404;
            break; 
        }
    }

    for (int i = 0; i < 2; i++)
    {
        if (file3[i] != "nofile")
        {
            if (file3[i] == file3_H)
            {
                file3_status = i;
                break;
            }
            else { file3_status = 422; }
        }
        else
        {
            file3_status = 404;
            break;
        }
    }

    return { file1_status, file2_status, file3_status}; // Return all file status

主窗口.cpp

void mainwindow::on_pushButton_clicked()
{
    QFuture<std::tuple<int, int, int>> Hash = QtConcurrent::run(Gen, &HashGen::check_sequential);
    QFutureWatcher<std::tuple<int, int, int>>* watcher = new QFutureWatcher<std::tuple<int, int, int>>;
    connect(watcher, &QFutureWatcher<std::tuple<int, int, int>>::finished, this, &MafiaDEDLFox::AfterHash);
    watcher->setFuture(Hash);
}

另一个问题是我需要使用 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);
};

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)));
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 std::tuple 函数 QtConcurrentRun 获取(多)返回值 的相关文章

随机推荐

  • 如何在android中将UTC时间戳转换为设备本地时间

    我需要将从服务器获取的 UTC 时间戳转换为本地设备时间 目前 我的时间有 5 小时的差异 例如 当我发布到服务器时 发布时间显示为 5 小时前而不是一秒前 我该如何解决这个问题 下面是我所做的代码 long timestamp curso
  • 在 Spring Security 表单登录页面中获取原始请求 url

    我在我的 spring 安全配置文件中声明了以下内容 http www springframework org schema security spring security 2 0 1 xsd http www springframewo
  • 如何获取TextView的文字颜色?

    在给定的代码中 lbl 0 getTextColor 给出错误 但我不知道如何获取 java 文件中 textview 的文本颜色 请帮助我 public void angry View v if lbl 0 getTextColor Co
  • android中的权限请求代码

    请帮助我获取权限 WRITE EXTERNAL STORAGE 和 WRITE SETTINGS 的请求代码 另请让我知道请求代码的来源 一个简单的演示 Here thisActivity is the current activity i
  • Ember 数据 1.0.0:与每种类型的适配器和序列化器混淆

    我正在从 Ember 数据 0 13 迁移到 1 0 0 beta 根据文档https github com emberjs data blob master TRANSITION md https github com emberjs d
  • MS Access 插入不重复

    微软访问2003 表主 手机号文本 255 名字文本 255 姓氏文本 255 地址文本 255 表温度 手机编号文本 255 名字文本 255 姓氏文本 255 地址文本 255 主要有100条记录 临时有 30 条记录 两个表都有 10
  • 发送图像并使用 json 返回它?

    我试图使用 json 将图像发送到 php 中的 web 服务 但客户端 cnt 读取图像 当我把它还回来的时候
  • 在 Java 中创建不依赖 if-else 的工厂方法

    目前我有一个方法 它充当基于给定字符串的工厂 例如 public Animal createAnimal String action if action equals Meow return new Cat else if action e
  • 如何让CSS网格项占用剩余空间?

    我有一张用 CSS 网格布局构建的卡片 左侧可能有一个图像 右上角有一些文本 右下角可能有一个按钮或链接 在下面的代码中 如何使绿色区域占用尽可能多的空间 同时使蓝色区域占用尽可能少的空间 绿色应将蓝色区域尽可能向下推 https jsfi
  • 如何使用 Spring AsyncResult 和 Future Return

    我有一个公共接口 Synchronous 它暴露给多个服务层类 它的目的是根据传递的 id 查找对象图 执行一些业务逻辑 然后将其传递给 Spring 异步方法 Asynchronous doWork 来完成其余的任务 我正在尝试使用 Sp
  • 在 React 中如何设置文档标题?

    我想为我的 React 应用程序设置文档标题 在浏览器标题栏中 我尝试过使用反应文档标题 https github com gaearon react document title 似乎已经过时 和设置document title in t
  • 在尝试发送短信之前检查 Android 中的网络覆盖范围

    我想为 Android 智能手机创建一个应用程序来检查手机是否处于飞行模式 如果是 应用程序会使手机退出飞行模式 并检查是否有任何网络连接可以发送短信 当我说网络连接时 我指的是发送短信的手机网络覆盖范围 我不想检查互联网连接 如果有网络连
  • WPF DataGrid 网格线在另存为 PDF 时不可见

    我正在使用 DataGrid 来表示 WPF 应用程序中的一些数据 在我使用 PDFSharp 将具有 DataGrid 的特定 WPF 窗口保存到 PDF 的功能中 我遇到一个问题 即当以较小的查看百分比查看保存的 PDF 时 DataG
  • 我的 Rails 和 Cocoa 应用程序之间的 SHA1 哈希值不匹配

    我有一个 Cocoa 应用程序将一些数据以及该数据的 SHA1 哈希值发送到 Rails 应用程序 该应用程序验证数据和哈希值是否匹配 但它们不匹配 可以肯定的是 我已经记录了在 Rails 和 Cocoa 端散列到控制台的数据的十六进制版
  • 使用回溯的数独求解器

    我最近一直在研究回溯数独求解算法 目前我想问一下我应该如何将我的solve 方法从void更改为boolean 我正在使用一个非常简单的回溯算法 它目前工作正常 但我宁愿有一个布尔值而不是一个空值 因为有一个打印堆栈不是很好 Thanks
  • 如何截断C char*?

    就如此容易 顺便说一句 我正在使用 C 我已经阅读了 cplusplus com 的 cstdlib 库函数 但我找不到一个简单的函数 我知道字符的长度 我只需要erase最后三个字符 我可以使用 C 字符串 但这是用于处理文件 它使用 c
  • 计算一个字节中零和一的数量

    我之前发布了一个程序来查找一个字节中 1 的总数 现在我正在尝试查找一个字节中 0 的数量 以下是我的代码 MOV AL 1 MOV CX 08H MOV BX 0000H MOV DX 0000H Zero SHR AL 01H JZ e
  • 在 Android 中唤醒/睡眠时启动 Activity

    我想制作一个计时器 当 Android 设备被唤醒时开始计时 当 Android 设备设置为睡眠时停止计时 我什么也没找到 如何触发活动 通过唤醒 睡眠 我希望你能帮助我解决我的问题 我使用了像 timonvlad 所说的 Broadcas
  • C# 中的分段下载?

    请原谅我对这个问题的无知 我想用 C 编写一个应用程序 可以以相同的方式从服务器下载文件打倒他们 http www downthemall net 做 DownThemAll 似乎打开了四个到 HTTP 服务器的连接来下载同一文件 我只是想
  • 从 std::tuple 函数 QtConcurrentRun 获取(多)返回值

    您好 我有一个用于在 Qt 中生成某个文件的 MD5 的类 我使用元组从中返回多个值 我想在其他线程上运行它 因为生成所有文件 MD5 可能需要一些时间并且它的冻结 gui我决定使用Qt并发运行在其他线程上运行它 但到目前为止我对如何获取所