c++ - Qt::Concurrent 与成员函数映射

标签 c++ multithreading qt qtconcurrent

我想使用 QtConcurrent::mapped()功能,但要通过 QtConcurrent examples提供并试图找到一个可用的示例来扩展到我的使用一直很困难。

在示例中,Qt maps仅静态函数,不使用成员函数(在示例中发现了许多类似的映射变体,但不使用成员函数)。

问题:

QtConcurrent::map()将函数应用于不返回的序列或迭代器,即 QFuture<void> .但是我希望返回结果,即 QFuture<SomeStructOrType>来自成员函数。

我想在其中使用它的示例/场景是 UI 应用程序中的密集型工作负载,但一个简单的示例可能是:

class MainWindow : public QMainWindow {
     Q_OBJECT

  public:
     // The struct is to demonstrate a datatype more complex than int / QString
     struct IntStruct {
         int i;
     };

     MainWindow(QWidget* parent = nullptr);
     IntStruct doubleValue(IntStruct i);
     ~MainWindow();

private:
   Ui::MainWindow* ui;
   // To watch progress and act upon progress change
   QFutureWatcher<IntStruct> futureWatcher;

   // Member to keep track of mapped process
   QFuture<IntStruct> future;

   //...
}

实现是:

MainWindow::MainWindow(QWidget* parent)
     : QMainWindow(parent)
     , ui(new Ui::MainWindow)
{
     ui->setupUi(this);

     // Input Sequence/Iterator to perform doubleValue function on
     QList<IntStruct> intList = QList<IntStruct>();
     for (int i = 0; i < 1000; i++) {
         IntStruct s;
         s.i = qrand();
         intList.append(s);
     }

     // Watch future and report on result ready (process a result when done)
     connect(&futureWatcher, &QFutureWatcher<IntStruct>::resultReadyAt, this, [intList](int index){
         qDebug() << QString("[index = %1] value = %2").arg(QString::number(index), QString::number(intList.at(index).i));
     });

     //typedef IntStruct (MainWindow::*doubleValueFunction)(IntStruct);
     //doubleValueFunction memberFunction = this->doubleValue;             // this->doubleValue error: reference to non-static member function must be called ???

     // Run future - this doubleValue function should be a pointer to an instance function, how to do so?         
     future = QtConcurrent::mapped(intList, &MainWindow::doubleValue);
     futureWatcher.setFuture(future);
}

// Some complex member function
MainWindow::IntStruct MainWindow::doubleValue(MainWindow::IntStruct i)
{
    i.i *= i.i;
    return i;
}

我知道 QtConcurrent 允许 lambda,但是我需要使用成员函数。

我还尝试使用一个指向当前实例的指针和一个 lambda,但它给了我一个 schpiel 错误,你可以找到 here .

 future = QtConcurrent::mapped(intList, [this](IntStruct &i){
     this->doubleValue(i);
 });

长话短说 所以基本上,我该如何使用 QtConcurrent::mapped( ) 与成员函数(最好是非 lambda 版本)?


赏金问题更新

一些额外的信息:

这是在屏幕上显示的

enter image description here

编译时的错误日志:

..\ThreadTester\mainwindow.cpp: In constructor 'MainWindow::MainWindow(QWidget*)':
..\ThreadTester\mainwindow.cpp:27:69: error: no match for 'operator=' (operand types are 'QFuture<MainWindow::IntStruct>' and 'QFuture<void>')
      future = QtConcurrent::mapped(intList, &MainWindow::doubleValue);
                                                                     ^
In file included from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtCore/QFuture:1:0,
                 from ..\ThreadTester\thread.h:10,
                 from ..\ThreadTester\mainwindow.h:6,
                 from ..\ThreadTester\mainwindow.cpp:1:
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtCore/qfuture.h:59:7: note: candidate: QFuture<MainWindow::IntStruct>& QFuture<MainWindow::IntStruct>::operator=(const QFuture<MainWindow::IntStruct>&)
 class QFuture
       ^~~~~~~
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtCore/qfuture.h:59:7: note:   no known conversion for argument 1 from 'QFuture<void>' to 'const QFuture<MainWindow::IntStruct>&'
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtCore/qfuture.h:59:7: note: candidate: QFuture<MainWindow::IntStruct>& QFuture<MainWindow::IntStruct>::operator=(QFuture<MainWindow::IntStruct>&&)
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtCore/qfuture.h:59:7: note:   no known conversion for argument 1 from 'QFuture<void>' to 'QFuture<MainWindow::IntStruct>&&'
In file included from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentfilterkernel.h:48:0,
                 from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtConcurrent/qtconcurrentfilter.h:47,
                 from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtConcurrent/QtConcurrent:8,
                 from ..\ThreadTester\thread.h:11,
                 from ..\ThreadTester\mainwindow.h:6,
                 from ..\ThreadTester\mainwindow.cpp:1:
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentmapkernel.h: In instantiation of 'QtConcurrent::ThreadEngineStarter<T> QtConcurrent::startMapped(const Sequence&, Functor) [with T = void; Sequence = QList<MainWindow::IntStruct>; Functor = QtConcurrent::MemberFunctionWrapper1<MainWindow::IntStruct, MainWindow, MainWindow::IntStruct>]':
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtConcurrent/qtconcurrentmap.h:132:88:   required from 'QFuture<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType> QtConcurrent::mapped(const Sequence&, MapFunctor) [with Sequence = QList<MainWindow::IntStruct>; MapFunctor = MainWindow::IntStruct (MainWindow::*)(MainWindow::IntStruct); typename QtPrivate::MapResultType<void, MapFunctor>::ResultType = void]'
..\ThreadTester\mainwindow.cpp:27:69:   required from here
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentmapkernel.h:237:71: error: could not convert 'QtConcurrent::startThreadEngine(ThreadEngine*) [with ThreadEngine = QtConcurrent::SequenceHolder1<QList<MainWindow::IntStruct>, QtConcurrent::MappedEachKernel<QList<MainWindow::IntStruct>::const_iterator, QtConcurrent::MemberFunctionWrapper1<MainWindow::IntStruct, MainWindow, MainWindow::IntStruct> >, QtConcurrent::MemberFunctionWrapper1<MainWindow::IntStruct, MainWindow, MainWindow::IntStruct> >; typename ThreadEngine::ResultType = MainWindow::IntStruct]()' from 'QtConcurrent::ThreadEngineStarter<MainWindow::IntStruct>' to 'QtConcurrent::ThreadEngineStarter<void>'
     return startThreadEngine(new SequenceHolderType(sequence, functor));
                                                                       ^
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentmapkernel.h: In instantiation of 'bool QtConcurrent::MappedEachKernel<Iterator, MapFunctor>::runIteration(Iterator, int, QtConcurrent::MappedEachKernel<Iterator, MapFunctor>::T*) [with Iterator = QList<MainWindow::IntStruct>::const_iterator; MapFunctor = QtConcurrent::MemberFunctionWrapper1<MainWindow::IntStruct, MainWindow, MainWindow::IntStruct>; QtConcurrent::MappedEachKernel<Iterator, MapFunctor>::T = MainWindow::IntStruct]':
..\ThreadTester\mainwindow.cpp:36:1:   required from here
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentmapkernel.h:175:17: error: no match for call to '(QtConcurrent::MemberFunctionWrapper1<MainWindow::IntStruct, MainWindow, MainWindow::IntStruct>) (const MainWindow::IntStruct&)'
         *result = map(*it);
In file included from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtConcurrent/qtconcurrentfilter.h:48:0,
                 from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtConcurrent/QtConcurrent:8,
                 from ..\ThreadTester\thread.h:11,
                 from ..\ThreadTester\mainwindow.h:6,
                 from ..\ThreadTester\mainwindow.cpp:1:
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentfunctionwrappers.h:132:14: note: candidate: T QtConcurrent::MemberFunctionWrapper1<T, C, U>::operator()(C&, U) [with T = MainWindow::IntStruct; C = MainWindow; U = MainWindow::IntStruct]
     inline T operator()(C &c, U u)
              ^~~~~~~~
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentfunctionwrappers.h:132:14: note:   candidate expects 2 arguments, 1 provided
mingw32-make[1]: *** [Makefile.Debug:1117: debug/mainwindow.o] Error 1
mingw32-make[1]: *** Waiting for unfinished jobs....
mingw32-make[1]: Leaving directory 'C:/Users/CybeX/QtProjects/build-ThreadTester-Desktop_Qt_5_13_1_MinGW_32_bit-Debug'
mingw32-make: *** [Makefile:38: debug] Error 2

对我来说完全没有意义的是 mapped()返回一些数据类型 U。如果我更改了 QFuture<IntStruct>QFuture<void> ,每个人都很高兴,但我无法收集到任何违背 mapped() 目的的结果功能放在首位。

最佳答案

你必须使用 std::bind :

#include <functional>

# ....

future = QtConcurrent::mapped(intList,
                              std::bind(&MainWindow::doubleValue,
                                        this,
                                        std::placeholders::_1));

关于c++ - Qt::Concurrent 与成员函数映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62142024/

相关文章:

c++ - 在 C++ 文件中链接 mat.h

c++ - Visual C++ 2010 和 Qt(moc 等)

java - 修复线程不安全 Java 代码的策略?

Java:线程共享数据的框架

c++ - Pthreads:为 pthread_cond_wait 使用 While 循环背后的逻辑

C++ round(49.5) 在使用变量调用时返回 49(在 Qt 中)

c++ - 用c++编写一个简单的linux桌面环境

c++ - 从嵌套结构调用 protected 基类函数

c++ - 从管道读取输入时出现 scanf 问题

c++ - 方法接受函数指针的可变参数模板