У меня проблемы с сигналами Qt.
Я не понимаю, как работают DirectConnection
и QueuedConnection
?
Я был бы признателен, если бы кто-нибудь объяснил, когда использовать какой из них (пример кода будет оценен).
У меня проблемы с сигналами Qt.
Я не понимаю, как работают DirectConnection
и QueuedConnection
?
Я был бы признателен, если бы кто-нибудь объяснил, когда использовать какой из них (пример кода будет оценен).
Вы не увидите большой разницы, если только вы не работаете с объектами, имеющими разное сходство потоков. Допустим, у вас есть объекты QObject 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).
B
в A
— вы можете позволить пользователю двух классов определять, что должно произойти, когда somethingChanged
испускается из A
. Имеет ли это смысл?
- person Jacob Robbins; 30.12.2013
Qt::QueuedConnection
в качестве параметра? Причина, по которой я спрашиваю об этом, заключается в том, что во многих местах указание Qt::QueuedConnection
или direct является необязательным параметром. Означает ли это, что Qt сама принимает решение о том, поставить ли сигнал в очередь или вызвать напрямую?
- person TheWaterProgrammer; 16.04.2018
Qt::AutoConnection
. Если эмиттер и приемник находятся в одном потоке, используется DirectConnection
. В противном случае используется QueuedConnection
.
- person Jacob Robbins; 24.04.2018
Qt::QueuedConnection
? Даже если два потока совместно используют некоторые данные (которые оба могут читать или записывать)? Или когда поток A
передает некоторые данные через аргументы сигнала, который подключен к слоту в потоке B
?
- person today; 22.06.2018
QueuedConnection
позволяет пользователям из многих потоков вызывать слоты в QObject, не беспокоясь о том, являются ли методы этого объекта реентерабельными (поскольку цикл событий сериализует вызовы). Имеет ли это смысл?
- person Jacob Robbins; 22.06.2018
Qt::QueuedConnection
.
- person today; 23.06.2018
в дополнение к ответу Джейкоба Роббинса:
утверждение «Вы не заметите большой разницы, если только вы не работаете с объектами, имеющими разное сходство потоков» неверно;
отправка сигнала на прямое соединение в том же потоке немедленно выполнит слот, как простой вызов функции.
отправка сигнала соединению в очереди в том же потоке поставит вызов в очередь в цикле обработки событий потока, поэтому выполнение будет всегда происходить с задержкой.
Класс на основе QObject имеет соединение с самим собой в очереди
Ответ Джейкоба потрясающий. Я просто хотел бы добавить сравнительный пример для встроенного программирования.
Исходя из опыта работы со встроенными RTOS/ISR, было полезно увидеть сходство в Qt DirectConnection с вытесняющим поведением ISR и Qt QueuedConnection с сообщениями в очереди в RTOS между задачами.
Боковое примечание: исходя из опыта встраиваемых систем, мне трудно не определить поведение в программировании. Я никогда не оставляю спор как Авто, но это всего лишь личное мнение. Я предпочитаю, чтобы все было написано явно, и да, иногда это становится сложно!