QFutureWatcher 如何观看多个 tasks/futures 和 finished() 信号

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

我有一些任务,从 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 信号后。

此刻,我使用了两个 QFutureWatchers - 一个正在监视第一个运行的任务,另一个 - 如果第一个任务没有结束则开始并使用临时观察器和 临时插槽[=31 监视第二个任务=](代码相同,我创建它只是为了接收另一个带有相关数据的观察者信号)直到第一个任务结束。它观察了相同的代码,但我必须复制它等待第一个任务结束,因为 QFutureWatcher 没有包含完成信号和相关 watcher.result()`s 的队列..

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

2) QtConcurrent::run 没有 cancel() 插槽。我可以对一个序列项使用 map/mapped 函数吗? mapped API 是否已排队处理 tasks/finished 信号?我怎么能意识到这一点?谢谢!

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() method for mapped calculations.It is not clear from your question, how do you get futures, so it is hard to say more. You may read about 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)是有风险的,因为您可能有很多泄漏。这就是为什么QtConcurrent中没有"terminate"API。

P.S.请不要写那个I'm do it wrong with QThread。什么都好。我知道我在做什么。这是一个很好的示例,可以继承 QThread

Does Qt has any Queued task mechanism?

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

实施步骤:

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

备注:

  • Qt 会将您对 executeTask 的调用排队(只要您使用 4. 中描述的方法之一),它们将按顺序执行。
  • 要快速终止您的 Worker,您可以使用 QThread::requestInterruption 并使用 QThread::isInterruptionRequested.
  • 在您的 executeTask 方法中检查取消
  • 要强制终止您的 Worker,您可以使用 QThread::terminate.
  • 否则使用 QThread::quitQThread::wait 优雅地终止 worker 并等待所有任务执行完毕。