Signaux Qt (QueuedConnection et DirectConnection))

j'ai des problèmes avec les signaux Qt.

Je ne comprends pas comment DirectConnection et QueuedConnection fonctionne?

je serais reconnaissant si quelqu'un peut expliquer à utiliser (exemple de code serait appréciée).

35
demandé sur Louis Langholtz 2013-02-24 16:07:49

3 réponses

vous ne verrez pas beaucoup de différence à moins de travailler avec des objets ayant des affinités de fil différentes. Disons que vous avez QObjects A et B et ils sont tous les deux attachés à des fils différents. A a un signal appelé somethingChanged() et B a une fente appelée handleChange() .

Si vous utilisez une connexion directe

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

la méthode handleChange() fonctionnera effectivement dans le A 's thread. Fondamentalement, c'est comme si l'émission du signal appelle la méthode de slot "directement". Si B::handleChange() n'est pas thread-safe, cela peut causer des bugs (difficiles à localiser). À tout le moins, vous manquez les avantages du fil supplémentaire.

si vous changez la méthode de connexion en Qt::QueuedConnection (ou, dans ce cas, laissez Qt décider quelle méthode utiliser), les choses deviennent plus intéressantes. En supposant que le thread de B exécute une boucle d'événement, en émettant le signal affichera un événement dans la boucle d'événement B . La boucle d'événement fait la queue de l'événement, et éventuellement invoque la méthode de slot chaque fois que le contrôle y retourne (c'est la boucle d'événement). Cela rend la communication entre/parmi les threads dans Qt assez facile (encore une fois, en supposant que vos threads exécutent leurs propres boucles locales d'événements). Vous n'avez pas à vous soucier de serrures, etc. parce que la boucle d'événement sérialise les invocations de fente.

Note: Si vous ne savez pas comment changez l'affinité du fil de QObject, regardez dans QObject::moveToThread . Qui devrait vous obtenir a commencé.

Modifier

je dois clarifier ma phrase d'ouverture. Cela fait une différence si vous spécifiez une connexion en file d'attente - même pour deux objets sur le même thread. L'événement est toujours affiché dans la boucle d'Événement du thread. Ainsi, l'appel de méthode est toujours asynchrone, ce qui signifie qu'il peut être retardé dans imprévisible les moyens (en fonction d'autres événements que la boucle peut devoir traiter). Cependant, si vous ne spécifiez pas de méthode de connexion, la méthode directe est automatiquement utilisée pour les connexions entre objets sur le même thread (au moins C'est dans Qt 4.8).

68
répondu Jacob Robbins 2013-12-30 02:51:48

en plus de Jacob Robbins réponse:

l'énoncé" vous ne verrez pas beaucoup de différence à moins de travailler avec des objets ayant des affinités de fil différentes "est erroné ;

émettant un signal à une connexion directe dans le même thread exécute la fente immédiatement, tout comme un simple appel de fonction.

émettant un signal à une connexion Mise en file d'attente à l'intérieur du même thread l'appel dans la boucle d'événement threads, donc l'exécution toujours arrive en retard.

la classe basée sur QObject a une connexion de file d'attente vers elle-même

19
répondu t_3 2017-05-23 11:54:51

la réponse de Jacob est impressionnante. J'aimerais juste ajouter un exemple comparatif à la programmation intégrée.

venant d'un arrière-plan RTOS/ISR intégré, il a été utile de voir les similitudes entre la connexion directe de Qt et le comportement préventif des ISRs et la connexion QueuedConnection de Qt aux Messages mis en file d'attente dans un RTOS entre les tâches.

Side note: venant d'un arrière-plan intégré, il est difficile pour moi de ne pas définir le comportement dans la programmation. Je ne jamais laisser L'argument comme Auto, mais c'est juste une opinion personnelle. Je préfère que tout soit explicitement écrit, et oui, cela devient parfois difficile!

0
répondu user3934527 2017-06-29 15:08:14