7
votes

Comment faire QObject :: MOVETOTOTHREADAD () lorsque vous utilisez QThreadPool?

Je construis un petit serveur Web multithreaded. Les qtcpsockets sont récupérés dans le fil principal, puis remettent par qtconcurrent sur qthreadpool, ce qui finit par traiter les données et envoie une réponse.

Mon problème est que la prise est créée dans le fil principal et traitées dans une autre. Cela provoque des erreurs lorsque vous essayez d'écrire sur la prise: P>

socket->moveToThread(QThread::currentThread()).


0 commentaires

3 Réponses :



4
votes

EXTENDRE qtcpserver , réimplément incomingconnection (int socketDescriptor) et transmettez le descripteur de prise sur les threads de la piscine. Avoir le qRunnable créer le qtcpsocket à partir du descripteur et démarrez une boucle d'événement pour recevoir les signaux de ce socket.


0 commentaires

1
votes

Je serais également d'accord que l'attrape incomingingconnection (int) et créer la prise dans le thread du travailleur est le moyen d'aller ici.

Mais votre problème était un problème plus fondamental, permettez-moi de montrer une alternative qui résout le problème général (déplacement arbitraire QOBJECT S à des threads dans un piscine de thread):

  1. dans le fil principal: dissocier la prise de n'importe quel thread:

    socket-> movetothread (nullptr);

    Cela suspendra le traitement des événements de la prise. Puis transmettez-le à Qtconcurrent.

  2. dans la fonction exécutée sur la piscine de thread, vous peut appelez maintenant

    socket-> movetothread (QThread :: courantethread ());

    Cela redémarrera le traitement des événements.

    Avec toute chance, la prise aura ses notificateurs de socket ré-enregistrés avec la boucle d'événement du thread de travailleur, et vous pouvez servir la connexion du travailleur.

    Il y a deux les mises en garde importantes ici, bien que:

    • Vous ne devez pas placer les tâches de blocage du piscine de thread global ( qthreadpool :: globalinstance () ). Comme le nom de la fonction suggère, cette instance de piscine de thread est une ressource globale, partagée par tous les utilisateurs de Qtconcurrent et bloquant ses fils de travailleurs dans le meilleur cas réduit la capacité (ainsi, le débit) de la piscine et dans le pire des cas LOCK-LOCK.
    • Si vous utilisez la boucle d'événement des threads de travailleur (pour ne pas utiliser l'API synchrone de qtcpsocket , en raison du premier point), vous devez appeler qthread :: courantethread ( ) -> EXEC () pour le démarrer. Cela, cependant, est un appel de blocage et du planificateur de piscine de thread, le travailleur aura l'air occupé, de sorte qu'il ne lui rendra pas plus de tâches (c.-à-d. QRunnable s).

      Si vous souhaitez réellement mettre en œuvre un serveur TCP multi-threadé, vous devez donc rouler votre propre piscine de thread.


0 commentaires