Qt:qt无法将事件发送到不同线程拥有的对象 - 为什么

时间:2017-06-02 12:44:01

标签: c++ multithreading qt user-interface callback

我正在使用Qt开发一个应用程序,我希望从另一个不相关的类更新我的GUI,并在不同的线程中执行函数。

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

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

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

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

提前谢谢

1 个答案:

答案 0 :(得分:2)

你可能会被“发送事件”这句话甩掉。在Qt中,这个短语具有严格的技术含义。即:

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

  • 发布事件意味着使用QCoreApplication::postEvent,它将事件发布到接收对象线程的事件队列。接收器线程的事件循环稍后调用接收器上的QObject::event

当对象生活在不同的主题中时,您不能发送事件,只能发布。这指出了您的问题的根本原因/

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

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