QFutureWatcher 如何观察多个任务/期货和 finish() 信号

QFutureWatcher how to watch multiple tasks/futures and finished() signals

本文关键字:信号 finish 任务 何观察 观察 QFutureWatcher      更新时间:2023-10-16

我有一些任务,从QtConcurrent::run()开始。任务有QFutureWatcher .我知道QFutureWatcher只能监视一个未来,但是当我从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

此时,我使用两个 QFutureWatcher - 一个是监视第一个运行的任务,另一个 - 如果第一个任务没有结束,则启动并使用临时观察程序和临时槽监视第二个任务(代码相同,我创建它只是为了接收另一个带有相关数据的观察程序信号)直到第一个任务结束。它监视了相同的代码,但我必须复制它以等待第一个任务结束,因为QFutureWatcher没有带有已完成信号和相关 watcher.result() 的队列。

1) Qt有排队任务机制吗?或者我怎样才能捕捉到多个任务的未来?

2) QtConcurrent::run没有 cancel() 插槽。我可以对一个序列项使用映射/映射函数吗?映射的 API 是否对任务/已完成的信号进行了排队处理?我怎么能意识到这一点?感谢!

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()方法。从你的问题中不清楚,你如何获得期货,所以很难多说。你可以阅读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)是有风险的,因为您可能会有很多泄漏。这就是为什么QtConcurrent中没有"终止"API的原因。

附言请不要写我用QThread做错了。一切都很好。我知道我在做什么。这是一个很好的示例,其中QThread的继承是可以的。

Qt是否有任何排队任务机制?

Qt提供了一个强大的信号和时隙框架,非常适合这样的应用。

实施步骤:

  1. 创建一个工作线程类(QObject 派生),该类具有包含任务实现的槽executeTask(int foo, QString bar)
  2. 实例化一个QThread并使用QObject::moveToThread将 Worker 类实例移动到该 QThread
  3. 启动线程
  4. 通过发出连接到executeTask的信号或通过调用executeTask方法上的QMetaMethod::invoke来运行任务。

笔记:

  • Qt会将您的调用排队到executeTask(只要您使用4中描述的方法之一),并且它们将按顺序执行。
  • 要快速终止您的工作线程,您可以使用QThread::requestInterruption并使用QThread::isInterruptionRequestedexecuteTask方法中检查取消。
  • 要强制终止您的工作人员,您可以使用QThread::terminate .
  • 否则,请使用 QThread::quitQThread::wait 正常终止工作线程并等待所有任务都已执行。