[英]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++ signal
与QML slot
QObject::connect(this, SIGNAL(SignalUpdateData(QVariant)), myTextItemQObject, SLOT(slotUpdateData(QVariant)));
所有这些都很好。 没有崩溃,没有锁定,什么也没有。
根据我的理解,由于工作线程的函数正在触发回调,因此在收到回调时,执行控制位于工作线程上。 因此,当执行emit SignalUpdateData(someValue)
,我们仍在工作线程上。 据我以前在android
& java
经验所知,我们无法从应用程序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.