默认情况下,从工作线程发出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
机制对其进行了更新.
I am new to Qt
. I have worker thread that is an std::thread
. The worker thread function continuously fetches some some data in a loop. The size of the data is frequently updated on a Text
element on a QML
UI. I have a listener callback which is nothing but an std::function
and it gets called from the thread's function
. It sends me callbacks based on which I updated the Text
element on QML
. I update it using signal slot
mechanism.
以下是QML : Text
元素:
Text {
id: mytext
objectName: "mytextobject"
function slotUpdateData(someValue){
mytext = someValue
}
}
SignalUpdateData
与位于QML
侧的slotUpdateData
连接.每次从std::thread
获得数据事件回调时,我emit SignalUpdateData
都会更新UI
上的QML Text element
.
SignalUpdateData
is connected with slotUpdateData
which resides on QML
side. Every time I get the data event callback from the std::thread
, I emit SignalUpdateData
which updates the QML Text element
on UI
.
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.
As per my understanding, since the worker thread's function is triggering the callback, the execution control is on the worker thread when the callback is received. So when doing emit SignalUpdateData(someValue)
, we'er still on the worker thread. And as far as I know from my previous experience in android
& java
, we cannot update the UI from anywhere outside the main thread
of the application.
那么,这是如何工作的? emit SignalUpdateData(someValue)
是否将呼叫放入main UI thread's event loop
中?尽管我要求worker thread
进行调用,但Qt
是否仍在main thread
上进行UI更改?如果我的方法很好,那么对性能有影响吗?这样做的最佳建议是什么?
So, How is this working ? Is emit SignalUpdateData(someValue)
putting the call into the main UI thread's event loop
? Is Qt
still making the UI change on main thread
in spite of me calling for it from a worker thread
? If my approach is fine, then does it have performance implications ? What is the best recommendation to do this ?
我想对此非常确定&使它能够正常工作不只是幸运的.最好同时使用 Qt :: Connection_enum 方法?
推荐答案
您正以其应有的方式利用Qt!而且您偶然遇到了它:这是一个不错的设计的标志-它有效".为您万岁,为Qt万岁:)
You're leveraging Qt the way it was meant to be! And you've run into it accidentally: that's a sign of a decent design - it "just works". Hooray for you, hooray for Qt :)
之所以起作用,是因为Qt是专门为使其工作而设计的,并且您正在使用默认的自动连接,在这种情况下,它的存在理由将为您提供帮助.因此,您碰巧做对了所有事情:什么都不要改变!
It's working because Qt has been designed specifically to make it work, and you're using the default automatic connection whose raison d'être is to help you out in this specific case. So you happen to be doing everything right: change nothing!
当您发出信号时,Qt会获取相关的源对象和目标对象互斥量,并将接收对象的thread()
与QThread::currentThread()
进行比较.如果它们相同,则立即调用slot/functor:它发生在信号主体中,因此在信号返回之前调用slot.这是安全的,因为在安全的地方从其thread()
使用了目标对象.
When you emit a signal, Qt acquires relevant source and destination object mutexes, and compares the receiving object's thread()
to QThread::currentThread()
. If they are identical, the slot/functor is called immediately: it happens in the body of the signal, so the slot is called before the signal returns. This is safe as the target object is used from its thread()
, where it's safe.
如果target->thread() != QThread::currentThread()
,则QMetaCallEvent
排队到目标对象.该事件包含(等效于)插槽方法指针和该插槽传递的任何参数的副本. QObject::event
实现可处理事件并执行调用.目标对象线程的事件循环在调用堆栈上,因为它的工作是将排队的事件传递给对象.
If target->thread() != QThread::currentThread()
, then a QMetaCallEvent
is queued to the target object. The event contains the (equivalent of) slot method pointer and a copy of any parameters passed by the slot. The QObject::event
implementation handles the event and executes the call. The target object thread's event loop is on the call stack, since its job is to deliver the queued events to the object.
简而言之,以上是Qt::AutoConnection
的含义.如果您使用的是Qt::QueuedConnection
,则无论线程是什么,都适用第二种情况.如果您使用的是Qt::DirectConnection
,则无论哪种情况,第一种情况都适用.
The above is, in a nutshell the meaning of a Qt::AutoConnection
. If you're using Qt::QueuedConnection
, the 2nd case applies no matter what the threads are. If you're using Qt::DirectConnection
, the 1st case applies no matter what.
我的猜测是,在与Qt相关的SO问题中,非自动连接类型的使用中> 95%是不必要的,这是由于缺乏理解和诉诸于魔咒.
My guess is that >95% of the uses of a non-automatic connection type in Qt-related questions on SO are unnecessary and stem from lack of understanding and resorting to what amounts to magic incantations.
这篇关于默认情况下,从工作线程发出Qt :: signal会使UI在主线程上更新吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!