默认情况下,从工作线程发出Qt :: signal会使UI在主线程上更新吗? [英] Emitting a Qt::signal from worker thread makes the UI update on main thread by default?

查看:141
本文介绍了默认情况下,从工作线程发出Qt :: signal会使UI在主线程上更新吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是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++ signalQML 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆