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


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

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

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

3 35

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. Цикл событий помещает событие в очередь и в конечном итоге вызывает метод slot всякий раз, когда управление возвращается к нему (это цикл событий). Это позволяет довольно легко справляться с коммуникацией между потоками в Qt (опять же, предполагая, что ваши потоки выполняют свои собственные локальные циклы событий). Вам не нужно беспокоиться о замках и т. д. потому что цикл событий сериализует вызовы слотов.

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

Edit

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

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

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

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

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

Класс на основе QObject имеет соединение в очереди к самому себе

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

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

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