2017-06-02 92 views
1

我正在用Qt开发一个应用程序,从而我想用另一个不同线程中执行的函数更新我的GUI。Qt:qt不能将事件发送到不同线程拥有的对象 - 为什么

我使用标准C++构造函数std :: function和std :: bind从Qt GUI类注册了一个回调函数。

在试图从其他类执行GUI回调函数时,我的程序崩溃,“qt无法将事件发送给其他线程拥有的对象”。

我的问题是,这里发生了什么。为什么不能像这样在两个线程之间进行通信。是否有可能以某种方式解决这个问题,或者Qt是否不允许其他不相关的函数以这种方式更新GUI?

有关信息,我正在使用Windows上的portaudio库。它在不同的线程中执行回调。当我收到音频时,我尝试更新我的GUI。

预先感谢您

+0

[可能](https://stackoverflow.com/questions/638251/how-to-emit-cross-thread-signal-in-qt)[dupes](https://stackoverflow.com/questions/2086142/qt-signaling-across-threads-one-is-gui-thread),但它们相当老。 [这一个](https://stackoverflow.com/questions/40382820/how-to-leverage-qt-to-make-a-qobject-method-thread-safe)不太适合这个问题,但现代和应该回答这个问题。 – nwp

+0

您可以尝试提出有关Java Swing的相同问题。 Java的发明者首先创建了一个名为AWT的多线程窗口工具包,但是它的工作原理是一个比他们预期的更难的问题。最终,他们放弃了AWT,并创建了一个名为Swing的新的单线程工具包。他们制作Swing单线程的原因可能适用于任何语言的任何窗口工具包。我不记得我在哪里阅读过这篇文章,但您可能可以使用Google找到它。 –

+0

谢谢。我认为对我来说最简洁的方式可能是在按下按钮或其他东西时启动在我的GUI上运行的QThread。 QThread然后将轮询我的其他类的标志并相应地更新GUI。我通常不喜欢投票,但你认为这是我最好的(或唯一的)选项吗? – Engineer999

回答

2

您可能被“发送事件”短语所抛弃。在Qt中,这个短语具有严格的技术含义。即:

  • 发送事件表示使用QCoreApplication::sendEvent,然后立即在接收器上调用QObject::event发送和接收线程不同时发送事件是错误的

  • to post事件表示使用QCoreApplication::postEvent,它将事件发送到接收对象线程的事件队列。接收器上的QObject::event稍后由接收器线程的事件循环调用。

当对象居住在不同的线程,你不许发送事件,只他们。这指出了您的问题的根本原因/

您在QWidget或派生类上访问的任何方法必须在其thread()(即主线程)上访问。 QWidget里面的所有内容都可以随意使用sendEvent作为发送线程和接收对象的线程按合同相同。通过从错误的线程调用QWidget方法,您通过间接使用sendEvent来中断该合同,从而失败。

只有您自己实施并且线程安全的方法可以从其他线程调用 - 并且它们不能使用sendEvent

相关问题