Как Qt::DirectConnection действует при использовании в многопоточной среде?

Хотя Qt::QueuedConnection или Qt::AutoConnection (в некоторых случаях) предпочтительнее в многопоточной среде, я задаю этот вопрос для понимания цели.

  1. Если сигнал MySignal() испускается в потоке A и слоте MySlot() принадлежит объекту потока B. Оба соединены через Qt::DirectConnection, как происходит казнь? т.е. если поток A отправляет сигнал потоку B, в то время как поток B выполняется в середине некоторой функцииfoo(). Будет ли слотMySlot() называться сразу после foo() финиширует или будет называться параллельно foo()?

  2. Есть ли сценарий, когда Qt::DirectConnection желательно по сравнению с другими в многопоточном приложении?

2 ответа

Есть ли сценарий, когда DirectConnection желательно по сравнению с другими в многопоточном приложении?

Да, если ваша ветка Bвыполняется только в одной функции и не имеет цикла событий, тогдаDirectConnectionэто единственный выбор, который у вас есть. С помощьюAutoConnection или QueuedConnection не будет работать, потому что соответствующее событие вызова слота не будет обработано в B или где-нибудь еще.

Еще одна причина для DirectConnectionможет быть, если ваши параметры не сериализуемы / десериализуемы с использованием системы метаобъектов Qt. Если условия дляQt::DirectConnection удовлетворены (слот является потокобезопасным), вы можете использовать его вместо этого (опасайтесь последствий - см. следующий текст).

Еще одна вещь, которую вы должны принять во внимание, - это распределение сигнала по нескольким слотам. Если вы используетеDirectConnectionи слот должен ждать мьютекса, другие слоты, которые были подключены после этого, не будут активированы, пока слот не вернется. С помощьюQueuedConnectionв этом случае будет обеспечено неблокирующее распространение сигнала. Затем поток B будет блокироваться (в своем внутреннем обработчике событий qt для события вызова слота) вместо потока A в своем операторе "emit".

Еще одна вещь, которую вы должны принять во внимание, - это порядок вызова слотов. Если вы выдаете несколькоemit операторы один за другим, а слоты одного и того же объекта вызываются с использованием QueuedConnection, они вызываются в этом порядке, потому что за ними стоят обычные события вызова слота. Если некоторые из этих слотовDirectConnection, то они вызываются синхронно в передающем потоке, без гарантии порядка относительно других вызовов слотов в очереди!

Изменить: я думаю, что с QObject::deleteLater тоже есть интересный случай. Рекомендую подключиться к нему с помощьюQt::DirectConnection. Эта функция является потокобезопасной и отправляет событие последующего удаления в целевой поток объекта. Более того, функция также обрабатывает случай, когда поток объекта не имеет запущенного цикла обработки событий (в этом случае объект удаляется при выходе из его потока). Если бы вы использовалиQt::QueuedConnection и в целевом потоке нет цикла событий, вы бы создали утечку памяти.

Если поток A отправляет сигнал потоку B, а поток B выполняется в середине некоторой функции foo(). Будет ли слот MySlot() вызываться сразу после завершения foo () или он будет вызываться параллельно с foo()?

К сожалению (и как вы подозреваете) Qt::DirectConnection именно это и B::MySlot() будет вызываться в потоке A одновременно с тем, что уже происходит в потоке B - foo()в этом случае. Таким образом, без какой-либо другой формы синхронизации использованиеQt::DirectConnection как правило, плохая идея, когда отправитель и получатель могут находиться в разных потоках.

Если вы действительно делаете потребуется понятие синхронного поперечного потока сигналов / слотов вызова, то вы можете посмотреть на Qt::BlockingQueuedConnection

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