【问题标题】:QMetaObject::invokeMethod returns true, but method is never calledQMetaObject::invokeMethod 返回 true,但从不调用方法
【发布时间】:2010-12-30 09:44:08
【问题描述】:

我正在尝试使用 QMetaObject::invokeMethod 在 GUI 线程上运行一个方法,该方法返回 true。但是,如果我使用 Qt::QueuedConnection 我的方法永远不会被调用(即使 invokeMethod 返回 true)。

这是我正在使用的:

QMetaObject::invokeMethod(this, "draw_widgets", Qt::QueuedConnection)

我没有收到任何错误消息或任何东西... 如果我使用 Qt::AutoConnection 或 Qt::DirectConnection 该方法确实会被调用,但当然来自同一个线程。不是来自 GUI 线程,这是我需要的。

draw_widgets 是一个 void draw_widgets() 类型的公共插槽 我的类继承了 QObject 并使用了 Q_OBJECT 宏。

我将不胜感激任何帮助,或者如何检查为什么没有调用该方法。

谢谢。

【问题讨论】:

  • 我有类似的情况:我有一个继承自 QObject 并使用Q_OBJECT 的类。这个类的实例是在主循环中创建的。然后,在主循环中执行同一类的方法时,我调用QMetaObject::invokeMethod(this, "hideListsSlot", Qt::QueuedConnection);,其中void hideListsSlot() 是该类的公共槽。插槽永远不会被调用。

标签: c++ user-interface qt multithreading


【解决方案1】:

“true”表示消息已成功排队。这并不意味着队列中的消息曾经被处理过......

假设您的程序有 10 个线程 (Thread1-Thread10)。您将来自 Thread7 的消息排队。它将排队到哪个线程?什么时候处理这​​个队列上的项目?

答案是每个QObject 都有一个叫做Thread Affinity 的东西,这是运行排队槽的线程。默认关联是与创建对象的线程相关(但您可以使用QObject::moveToThread() 更改它。)

如果您想将某些内容排队到 GUI 线程,那么由您的 this 指针指定的对象应该具有 GUI 线程的亲和性。您可以使用QObject::thread() 方法进行检查。

但无论如何,无论您排队到哪个线程...您都必须在该线程上运行某种消息泵。例如看QThread::exec()。如果您的线程亲和性与 GUI 相关,那么可能已经是这种情况了,因为您正在运行应用程序的 exec。

(作为旁注,通常不需要直接调用QMetaObject::invokeMethod。您可以创建一个信号并将其绑定到一个插槽,然后发出信号来代替调用。)

【讨论】:

  • 非常感谢您的回答。我不知道线程亲和力。更改对象与 GUI 线程的亲和性解决了这个问题。
  • @HostileFork 对面的旁注,如果你有太多槽,它会创建与槽相同的信号,所以在这种情况下使用QMetaObject::invokeMethod(this, "slot 1 ... n", Qt::QueuedConnection) 是公平的。
  • @HostileFork 对面的旁注继续,invokeMethod 调用应该放在条件检查if (QThread::currentThread() != thread()) 内的插槽中。这样客户端就可以直接调用slots了。
猜你喜欢
  • 2021-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多