繁体   English   中英

从工作线程发出Qt :: signal默认情况下会在主线程上更新UI?

[英]Emitting a Qt::signal from worker thread makes the UI update on main thread by default?

我是Qt新手。 我有一个工作线程,它是一个std::thread 辅助线程函数连续循环获取一些数据。 数据大小经常在QML UI的Text元素上更新。 我有一个监听器回调,只不过是一个std::function ,它是从thread's function 它向我发送回调,基于这些回调我更新了QML上的Text元素。 我使用signal slot机制对其进行更新。

以下是QML : Text元素:

Text {
  id: mytext
  objectName: "mytextobject"

  function slotUpdateData(someValue){
    mytext = someValue
  }
}

SignalUpdateData与位于QML侧的slotUpdateData连接。 每次从std::thread获得数据事件回调时,我emit SignalUpdateData来更新UI上的QML Text element

void CallBackReceivedFromWorkerThread(float someValue) {
  emit SignalUpdateData(someValue)
}

以下是我如何将此C++ signalQML slot

QObject::connect(this, SIGNAL(SignalUpdateData(QVariant)), myTextItemQObject, SLOT(slotUpdateData(QVariant)));

所有这些都很好。 没有崩溃,没有锁定,什么也没有。

根据我的理解,由于工作线程的函数正在触发回调,因此在收到回调时,执行控制位于工作线程上。 因此,当执行emit SignalUpdateData(someValue) ,我们仍在工作线程上。 据我以前在androidjava经验所知,我们无法从应用程序main thread之外的任何位置更新UI。

那么,这如何运作? 是否emit SignalUpdateData(someValue)将调用放入main UI thread's event loop 尽管我从worker thread调用它,但Qt仍在对main thread进行UI更改吗? 如果我的方法很好,那么对性能有影响吗? 这样做的最佳建议是什么?

我想对此非常确定,而不仅仅是能使它工作起来很幸运。 我是否也应该使用Qt :: Connection_enum以获得最佳方法?

您正在按原定的方式利用Qt! 而且您偶然遇到了它:这是一个不错的设计的标志-它“有效”。 为您万岁,为Qt万岁:)

之所以起作用,是因为Qt是专门为使其工作而设计的,并且您正在使用默认的自动连接,在这种情况下,它的存在理由将为您提供帮助。 因此,您恰好做对了所有事情:什么都不要改变!

当您发出信号时,Qt将获取相关的源对象和目标对象互斥量,并将接收对象的thread()QThread::currentThread() 如果它们相同,则立即调用slot / functor:它发生在信号主体中,因此在信号返回之前调用slot。 这是安全的,因为可以从目标对象的thread()使用目标对象。

如果target->thread() != QThread::currentThread() ,则QMetaCallEvent排队到目标对象。 该事件包含(等效于)插槽方法指针和该插槽传递的任何参数的副本。 QObject::event实现处理事件并执行调用。 目标对象线程的事件循环在调用堆栈上,因为它的工作是将排队的事件传递给对象。

简而言之,以上是Qt::AutoConnection的含义。 如果您使用的是Qt::QueuedConnection ,则无论线程是什么, Qt::QueuedConnection情况都适用。 如果您使用的是Qt::DirectConnection ,则第一种情况无论如何都适用。

我的猜测是,在与Qt有关的SO问题中,非自动连接类型的使用中> 95%是不必要的,并且是由于缺乏理解和诉诸于魔咒。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM