Подтвердить что ты не робот

Qt-сигналы (QueuedConnection и DirectConnection)

У меня возникают проблемы с сигналами Qt.

Я не понимаю, как работают DirectConnection и QueuedConnection?

Я был бы признателен, если кто-нибудь объяснит, когда использовать какой из них (пример кода будет оценен).

4b9b3361

Ответ 1

Вы не увидите большой разницы, если не работаете с объектами, имеющими разные сходства нитей. Скажем, у вас есть QObjects A и B, и они оба прикреплены к различным потокам. A имеет сигнал с именем somethingChanged() и B имеет слот под названием handleChange().

Если вы используете прямое соединение

connect( A, SIGNAL(somethingChanged()), B, SLOT(handleChange()), Qt::DirectConnection );

метод handleChange() будет фактически выполняться в потоке A. В принципе, он как бы излучает сигнал, вызывает метод "прямо". Если B::handleChange() не является потокобезопасным, это может вызвать некоторые (трудные для поиска) ошибки. По крайней мере, вы упускаете преимущества дополнительного потока.

Если вы измените метод подключения на Qt::QueuedConnection (или, в этом случае, пусть Qt решит, какой метод использовать), все становится интереснее. Предполагая, что поток B запускает цикл событий, излучение сигнала отправляет событие в цикл событий B. Цикл событий останавливает событие и в конечном итоге вызывает метод слота всякий раз, когда управление возвращается к нему (это цикл события). Это делает довольно простой способ связи между/между потоками в Qt (опять же, если ваши потоки запускают собственные локальные циклы событий). Вам не нужно беспокоиться о блокировках и т.д., Потому что цикл событий сериализует вызовы слота.

Примечание. Если вы не знаете, как изменить аффинность потока QObject, загляните в QObject::moveToThread. Это должно заставить вас начать.

Edit

Я должен уточнить свое вступительное предложение. Это имеет значение, если вы указываете соединение в очереди - даже для двух объектов в одном потоке. Событие по-прежнему отправляется в цикл событий потока. Таким образом, вызов метода по-прежнему является асинхронным, то есть он может задерживаться непредсказуемыми способами (в зависимости от любых других событий, которые цикл может потребовать для обработки). Однако, если вы не указали метод подключения, прямой метод автоматически используется для соединений между объектами в одном и том же потоке (по крайней мере, в Qt 4.8).

Ответ 2

в дополнение к Jacob Robbins ответ:

утверждение "Вы не увидите большой разницы, если вы не работаете с объектами, имеющими разные аффинности нитей", неверно;

излучение сигнала на прямое соединение внутри одного потока будет немедленно выполнять слот, как простой вызов функции.

излучение сигнала в очередь в одном потоке вызовет вызов в цикл событий потоков, поэтому выполнение всегда будет задерживаться.

Класс QObject имеет связанное с ним соединение

Ответ 3

Ответ Джейкоба потрясающий. Я просто хотел бы добавить сравнительный пример для встроенного программирования.

Исходя из встроенного фона RTOS/ISR, было полезно увидеть сходство в Qt DirectConnection с превентивным поведением ISR и Qt QueuedConnection для сообщений в очереди в RTOS между задачами.

Боковое примечание: Исходя из встроенного фона, мне трудно не определять поведение в программировании. Я никогда не оставляю аргумент как Авто, но это только личное мнение. Я предпочитаю, чтобы все было явно написано, и да, что становится трудным время от времени!