QFutureWatcher 如何观察多个任务/期货和 finish() 信号
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
。
此时,我使用两个 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提供了一个强大的信号和时隙框架,非常适合这样的应用。
实施步骤:
- 创建一个工作线程类(QObject 派生),该类具有包含任务实现的槽
executeTask(int foo, QString bar)
。 - 实例化一个
QThread
并使用QObject::moveToThread
将 Worker 类实例移动到该 QThread - 启动线程
- 通过发出连接到
executeTask
的信号或通过调用executeTask
方法上的QMetaMethod::invoke
来运行任务。
笔记:
- Qt会将您的调用排队到
executeTask
(只要您使用4中描述的方法之一),并且它们将按顺序执行。 - 要快速终止您的工作线程,您可以使用
QThread::requestInterruption
并使用QThread::isInterruptionRequested
在executeTask
方法中检查取消。 - 要强制终止您的工作人员,您可以使用
QThread::terminate
. - 否则,请使用
QThread::quit
和QThread::wait
正常终止工作线程并等待所有任务都已执行。
- Qt VTK交互风格的信号到小部件
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何在没有信号的情况下从C++执行QML插槽
- 线程之间的布尔停止信号
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 当用户在qtablewidget中输入单元格时,如何获得信号?C++
- 有可能在信号处理程序中设置promise吗
- 代码在我的计算机上运行良好,但是在将其提交给coursera时遇到未知的信号11问题
- 在条件变量中触发错误信号的频率是多少
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 调试和自由执行中的信号处理
- 升压信号2将插槽传递到成员功能以断开连接
- C++函数包装器来捕获某些信号
- 如何在qt中将信号和插槽与另一个对象连接 --解决了
- 中止信号来自 C++ 中的中止(3) (SIGABRT)
- Qt将信号与另一个类方法连接
- 什么时候会有QNetworkReply::error信号后跟一个finish()信号
- 无法在多个 Qthread的 QThread 和 finish() 信号之间连接
- QFutureWatcher 如何观察多个任务/期货和 finish() 信号