我有一些任务,从QtConcurrent::run()
开始。
任务有QFutureWatcher
。我知道QFutureWatcher
可以观看只有一个 Future,但是当我从UI启动相同的任务时,如何在每个任务上创建`QFutureWatcher *?是吗:
QFutureWatcher<void> *watcher = new QFutureWatcher;
watcher->setFuture(future);
QVector<QFutureWatcher<void>*> watchers;
watchers.push_back(watcher); // vector with pointers to each tasks watchers
还是其他什么?
*我的麻烦是我从我的代码启动每个任务,但是使用外部DLL函数执行的任务。我没有API来阻止任务。在收到完成的QFutureWatcher
信号后,我只能等待任务结束并关闭任务并释放所有相关数据。
此时,我使用了两个QFutureWatchers - 一个正在观看第一个运行的任务,另一个是 - 如果第一个任务没有结束则启动并且使用临时观察者和临时插槽观看第二个任务(编码同样,我创建它只是为了接收带有相关数据的另一个观察者信号,直到第一个任务结束。它看了相同的代码,但我必须复制它等待第一个任务结束,因为QFutureWatcher
没有完成信号的队列和相关的watcher.result()`s ..
1)Qt是否有任何排队任务机制?或者我怎样才能抓住多个任务未来?
2)QtConcurrent::run
没有cancel()插槽。我可以将map / mapped函数与一个序列项一起使用吗?映射的API是否排队处理任务/完成信号?我怎么能意识到这一点? THX!
答案 0 :(得分:3)
1)你可以使用这样的东西(只是代码草案):
class MultiWatcher
: public QThread
{
Q_OBJECT
signals:
void allDone();
public:
void run() override;
QFutureSynchronizer _sync;
};
void MultiWatcher::run()
{
_sync.waitForFinished();
emit allDone();
}
class Test
: public QObject
{
Q_OBJECT
public:
//...
void do();
void onDone();
};
void Test::do()
{
// fill some futures
auto w = new MultiWatcher();
w->_sync.addFuture( f1 ); // Not thread-safe
w->_sync.addFuture( f2 );
w->_sync.addFuture( f3 );
// ...
connect( w, &MultiWatcher::allDone, this, &Test::onDone );
w->start();
}
void Test::onDone()
{
sender()->deleteLater();
qDebug() << "All futures are done";
}
//...
test->do();
2)映射计算有QFuture::cancel()
方法。你的问题不清楚,你如何获得期货,所以很难说更多。如果你有一些问题,你可以阅读concurrency in Qt并提出更多问题。
QFuture::cancel
无法与QtConcurrent::run
一起使用,您需要在线程代码中设计另一个中断机制。例如:
std::atomic_bool _isRunning = true; // somewhere in code
void MyWorker::doWork()
{
while (_isRunning)
{
// Do next step of computation
}
}
// Use _isRunning = false; to interrupt. It's thread-safe.
但是中断你不管理的代码(来自外部.dll)是有风险的,因为你可能有很多泄密。这就是为什么没有&#34;终止&#34; QtConcurrent中的API。
P.S。请不要写I'm do it wrong with QThread。一切都很好。我知道我在做什么。这是一个很好的示例,其中QThread
的继承是可以的。
答案 1 :(得分:1)
Qt是否有任何排队任务机制?
Qt提供了强大的信号和插槽框架,非常适合这种应用。
实施步骤:
executeTask(int foo, QString bar)
。QThread
并使用QObject::moveToThread
executeTask
的信号或通过QMetaMethod::invoke
方法调用executeTask
来运行任务。注意:
executeTask
(只要您使用其中一种方法),它们将按顺序执行。 QThread::requestInterruption
并使用executeTask
检查QThread::isInterruptionRequested
方法中的取消。QThread::terminate
。QThread::quit
和QThread::wait
优雅地终止工作程序,并等待所有任务都执行完毕。