Сигналы Qt (QueuedConnection и DirectConnection)

У меня проблемы с сигналами Qt.

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

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

3 ответа

Решение

Вы не увидите большой разницы, если не будете работать с объектами, имеющими различную привязку к потокам. Допустим, у вас есть 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, Это должно начать вас.

редактировать

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

В дополнение к ответу Джейкоба Роббинса:

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

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

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

Класс, основанный на QObject, имеет соединение с очередями

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

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

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

Другие вопросы по тегам