2016-11-21 4 views
1

Я новичок в Qt. У меня есть рабочий поток, который является std::thread. Функция рабочего потока непрерывно извлекает некоторые данные в цикле. Размер данных часто обновляется на элементе Text на интерфейсе QML. У меня есть обратный вызов слушателя, который является ничем иным, как std::function, и он вызывается из thread's function. Он отправляет мне обратные вызовы, на основании которых я обновил элемент Text на QML. Я обновляю его с помощью механизма signal slot.Извлечение сигнала Qt :: из рабочего потока делает обновление пользовательского интерфейса по основному потоку по умолчанию?

Ниже приводится QML : Text элемент:

Text { 
    id: mytext 
    objectName: "mytextobject" 

    function slotUpdateData(someValue){ 
    mytext = someValue 
    } 
} 

SignalUpdateData связан с slotUpdateData который находится на стороне QML. Каждый раз, когда я получаю обратный вызов события данных из std::thread, I emit SignalUpdateData, который обновляет QML Text element по адресу 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.

Итак, Как это работает? Есть emit SignalUpdateData(someValue), ставящий вызов в main UI thread's event loop? Is Qt все еще делает изменение пользовательского интерфейса на main thread, несмотря на то, что я вызываю его из worker thread? Если мой подход в порядке, то это имеет последствия для производительности? Какая рекомендация для этого?

Я хочу быть очень уверенным в этом & не просто повезло, что заставило это работать. Должен ли я использовать Qt::Connection_enum, а также для наилучшего подхода?

+1

Насколько я знаю (может быть, не так), все QML происходит в потоке main/gui. –

ответ

7

Вы используете Qt так, как должно было быть! И вы случайно столкнулись с этим: это признак приличного дизайна - он «просто работает». Hooray for you, hooray for Qt :)

Он работает, потому что Qt был разработан специально, чтобы заставить его работать, и вы используете автоматическое соединение по умолчанию, чья raison d'être поможет вам в этом конкретном случае. Таким образом, вы, кажется, все делаете правильно: ничего не меняйте!

Когда вы излучаете сигнал, Qt получает соответствующие мьютексы объекта и объекта назначения и сравнивает thread() принимающего объекта с QThread::currentThread(). Если они идентичны, слот/функтор вызывается немедленно: он происходит в теле сигнала, поэтому слот вызывается до того, как сигнал возвращается. Это безопасно, поскольку целевой объект используется из его thread(), где он безопасен.

Если target->thread() != QThread::currentThread(), то QMetaCallEvent поставлен в очередь на целевой объект. Событие содержит указатель метода (эквивалент) слота и копию любых параметров, передаваемых слотом. Реализация QObject::event обрабатывает событие и выполняет вызов. Цикл событий потока объекта-объекта цели находится в стеке вызовов, поскольку его задача заключается в доставке событий в очередь на объект.

Выше, в двух словах, значение Qt::AutoConnection. Если вы используете Qt::QueuedConnection, второй случай применяется независимо от того, что такое потоки. Если вы используете Qt::DirectConnection, первый случай применяется независимо от того, что.

Я полагаю, что> 95% использования неавтоматического типа соединения в Qt-связанных вопросах на SO не является необходимым и связано с непониманием и прибеганием к тому, что составляет магические заклинания.

+0

Не могли бы вы также указать, по большому счету, где эти вещи реализованы в исходном коде Qt? – Paul

+0

@Paul В основном это реализация ['QObject'] (https://code.woboq.org/qt5/qtbase/src/corelib/kernel/) и, конечно же, она сотрудничает с системой метаданных. –

+1

http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qobject.cpp#n3690 – BaCaRoZzo

Смежные вопросы