使用 QFuture 调用本地类函数

Posted

技术标签:

【中文标题】使用 QFuture 调用本地类函数【英文标题】:Using QFuture to call a local class function 【发布时间】:2013-04-23 12:37:39 【问题描述】:

我有一个 UI 程序,我在其中使用 QFuture 在不同的类中运行一个函数,该类对处理器等很重,并导致我的 UI 崩溃,在使用 QFuture 将其线程化后它工作正常,但是我有另一个函数需要在之后立即调用,但是这个函数与我调用它的位置在同一个类中。

我使用相同的代码来执行第二个代码,但它只显示关于 Timers 的错误,我什至没有使用,我也不知道我在论据:

future = new QFuture<void>;

*future = QtConcurrent::run(this, &GUI::test);

test 是一个本地函数,这是否与我不能有两个并发 ::run 调用或其他什么有关,我尝试查看文档,但不幸的是没有帮助

基本上当这被称为 UI 锁定并且我收到一些奇怪的警告时,我认为线程化的重点是 UI 不会崩溃

【问题讨论】:

Qt 小部件具有线程亲和性,您是否在测试中做任何必须在 GUI 线程上完成的事情,例如访问任何小部件的状态?这将解释锁定。哦,线程的重点是 UI 不应该被长操作阻塞,而不是它不会崩溃。线程太容易崩溃;) 我更新了 qGraphicsView 的场景?,任何想法为什么我可能会得到这个错误,但当我不做任何事情时 QObject::startTimer: timers cannot be started from another thread 我猜你在内部做的事情会启动一个计时器。 那么如果我没有对象可以调用停止,我怎么能停止它,因为我从未创建过对象,并且我使用与上面完全相同的代码来调用不同的函数并且它没有提到计时器注意两个函数中都没有使用计时器 对此有何建议? 【参考方案1】:

这是我对此的最佳猜测。

我猜你有以下情况。 (注意:在尝试为问题提出解决方案时,了解您所处的情况非常有用。通常事实证明,OP 正在以一种根本错误的方式处理某事,并且应该做一些完全不同的事情。)

你有一个图形用户界面。您有一个需要很长时间的操作,您想在工作线程中运行该操作。并且在长操作结束时,你需要在 GUI 线程上调用一个函数,可能是为了更新 GUI 或类似的东西。

所以你使用 QtConcurrent::run(&someObject, &SomeObject::task) 启动后台任务。然后,您需要通过某种方式在任务完成时在 GUI 线程上收到通知。

执行此操作的正确方法是将 QtFutureWatcher 附加到从 run() 返回的未来,并将 GUI 类上的插槽连接到其完成的信号。 Qt 的信号机制将确保槽在正确的线程上被调用。

【讨论】:

对不起,我的代码没有完成需要很长时间的函数使用上面显示的代码在线程上运行我有一个观察者等待完成的信号,当它得到它调用一个插槽时它再次使用与上面相同的代码调用一个函数,该函数在我的 UI 上更新场景,观察者再次等待完成信号,完成时调用一个插槽,它只是 std::cout 完成的消息,但我得到一个 ui 崩溃在我的 ui 上添加到场景的第二个功能??? 也许您不允许在工作线程中更新场景?我对 Qt 场景图了解不够。 是的,也许不是......它可以解释为什么 ui 只是说没有响应,即使它已被线程化。我在上面的评论中提到的计时器警告有什么想法吗? 如果您确保不在坏线程上调用任何内容,您是否仍会收到警告?如果是这样,看看您是否可以在发出警告的 Qt 函数上设置断点,在调试器下运行,并从警告发出回溯到您的代码,以找出警告的根本原因,即哪个函数您在内部使用的启动计时器。然后您可以尝试了解该计时器的创建位置,并确保这两个事件发生在同一个线程上。 我得到了帮助,但我的 Ui 功能和线程只是出现了一些问题,iv 在这里问了关于这个问题的 5 个问题,没有人能想出一个可行的解决方案......认为现在的问题是,显然你不能做任何不是主线程的ui,但它的ui东西需要很长时间并且需要线程soooooo我不知道该怎么做tbh我不相信是这样,但似乎没有人知道.. .

以上是关于使用 QFuture 调用本地类函数的主要内容,如果未能解决你的问题,请参考以下文章

QFutureWatcher 没有调用连接的插槽

Qt多线程:QtConcurrent + QFuture + QFutureWatcher

深入了解android平台的jni---本地多线程调用java代码

如何创建具有立即可用价值的 QFuture?

QFuture 内存泄漏

阻塞 QFuture.result() 或 QFutureWatcher.waitForFinished();