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

时间:2016-07-13 07:41:00

标签: c++ multithreading qt qtconcurrent qfuture

我有一些任务,从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!

2 个答案:

答案 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提供了强大的信号和插槽框架,非常适合这种应用。

实施步骤:

  1. 创建一个工人类(QObject派生),其中包含一个包含任务实现的插槽executeTask(int foo, QString bar)
  2. 实例化QThread并使用QObject::moveToThread
  3. 将您的Worker类实例移动到该QThread
  4. 启动主题
  5. 通过发送连接到executeTask的信号或通过QMetaMethod::invoke方法调用executeTask来运行任务。
  6. 注意:

    • Qt将您的呼叫排队到executeTask(只要您使用其中一种方法),它们将按顺序执行。
    • 要快速终止您的工作人员,您可以使用QThread::requestInterruption并使用executeTask检查QThread::isInterruptionRequested方法中的取消。
    • 要强制终止您的工作人员,您可以使用QThread::terminate
    • 否则,请使用QThread::quitQThread::wait优雅地终止工作程序,并等待所有任务都执行完毕。