QtConcurrent中的run()函数的使用 有两种模式: Basic模式和Promise模式.
好像Promise模式是Qt6里面新增的, 以前没有
Basic模式的使用: 使用1: 使用一个外部全局函数 1 2 3 4 5 6 7 8 9 extern void func1 () ;QFuture<void > future = QtConcurrent::run (func1); extern void func2 (int arg1, double arg2) ;int arg1 = ...;double arg2 = ...;QFuture<void > future = QtConcurrent::run (func2, arg1, arg2);
场景2: 重载的全局函数 1 2 3 4 5 6 7 8 9 10 11 12 13 void foo (int arg1) ;void foo (int arg1, double arg2) ;QFuture<void > future1 = QtConcurrent::run ([](){foo (42 );}); QFuture<void > future2 = QtConcurrent::run (static_cast <void (*)(int )>(foo), 42 ); QFuture<void > future3 = QtConcurrent::run (qOverload <int >(foo), 42 );
场景3: 获取返回值 1 2 3 4 5 QString foo () ;QFuture<QString> future = QtConcurrent::run (foo); ... QString result = future.result ();
场景4: 类成员函数 如果调用的是const成员函数, 因为不需要修改类实例, 可以以传值的方法进行. 如果调用的是非const成员函数, 则必须将类实例以指针的方法传进去. 注意参数的顺序: 先是类方法签名, 然后是类实例(或指针), 然后是依次的参数:
这个有点奇怪, 我印象中, 在Qt5中, 对象是第一个参数?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 QByteArray bytearray = "hello world" ; QFuture<QList<QByteArray> > future = QtConcurrent::run (&QByteArray::split, bytearray, ' ' ); ... QList<QByteArray> result = future.result (); QImage image = ...; QFuture<void > future = QtConcurrent::run (&QImage::invertPixels, &image, QImage::InvertRgba); ... future.waitForFinished ();
场景5: 传引用参数 下面的例子中, 使用std::ref
来表明引用:
1 2 3 4 5 static void addOne (int &n) { ++n; }... int n = 42 ;QtConcurrent::run (&addOne, std::ref (n)).waitForFinished ();
场景6: 使用Callable对象: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 struct TestClass { void operator () (int s1) { s = s1; } int s = 42 ; }; ... TestClass o; QtConcurrent::run (std::ref (o), 15 ).waitForFinished (); QtConcurrent::run (o, 42 ).waitForFinished (); QtConcurrent::run (TestClass (), 42 ).waitForFinished (); QtConcurrent::run (&o, 42 ).waitForFinished ();
带Promise的run 被执行的函数要带一个额外的QPromise<T>
引用类型的参数, 而T
是计算结果类型.
1 2 3 4 5 6 extern void foo (QPromise<void > &promise) ;QFuture<void > future = QtConcurrent::run (foo);
promise
参数会由run
函数初始化, 并将其引用传递给线程函数, 因此, 调用时不需要定义和使用这个参数:
1 2 3 4 5 6 7 8 extern void foo (QPromise<void >& promise, int arg1, double arg2) ;int arg1 = ...;double arg2 = ...;QFuture<void > future = QtConcurrent::run (foo, arg1, arg2);
执行中报告结果 Promise模式下的函数始终是返回void
类型, 它的结果是通过promise的addResult
来返回的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void foo (QPromise<QString>& promise) { ... promise.addResult ("Hellow" ); ... promise.addResult ("World" ); } QFuture<QString> future = QtConcurrent::run (foo); ... auto results = future.results ();...
挂起和取消执行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void foo (QPromise<int > &promise) { for (int i = 0 ; i < 100 ; ++i) { promise.suspendIfRequested (); if (promise.isCanceled ()) return ; const int res = ... ; promise.addResult (res); } } QFuture<int > future = QtConcurrent::run (foo); ... future.suspend (); ... future.resume (); ... future.cancel ();
上报中间结果 它使用promise
的setProgressValue()
函数来设置进度, 并且使用QFutureWatcher::progressValueChange
信号.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void foo (QPromise<int > &promise) { promise.setProgressRange (0 , 100 ); int result = 0 ; for (int i = 0 ; i < 100 ; ++i) { const int part = ... ; result += part; promise.setProgressValue (i); } promise.addResult (result); } QFutureWatcher<int > watcher; QObject::connect (&watcher, &QFutureWatcher::progressValueChanged, [](int progress){ ... ; qDebug () << "current progress:" << progress; }); watcher.setFuture (QtConcurrent::run (foo));