8
votes

Comment exécuter Qtcpsocket dans un fil différent?

Comment exécuter les fonctions qtcpsocket dans un fil différent?


1 commentaires

Ce n'est pas possible . J'ai appris cela difficile. Voir Ma question . Ont soulevé une suggestion de bugs à qt à movetothread () = Supprimer pour ces sockets et classes de serveur. Qtbug-82373


4 Réponses :


2
votes

mettre un qmutex verrouille autour de tous les appels, pas seulement sur le thread "différent", mais sur tous les filets. Un moyen facile de le faire est via un qmutexocker


2 commentaires

" Remarque: Toutes les fonctions de cette classe sont réentrantes" . Si vous avez une source plus autoritaire pour votre revendication contradictoire, veuillez inclure cela.


Tu as raison. Cependant, (et ce que je voulais dire était) la classe n'est pas thread-coffre-fort, et la ré-entrante ne garantit que vous pouvez utiliser la classe à partir de plusieurs threads si vous avez des instances différentes, mais différent qtcpsocket Les instances ne peuvent pas partager des descripteurs de socket. De plus, une seule instance d'un qtcpsocket n'est pas accessible à partir de threads multiples, que ce soit muté de la mutilation.



6
votes

Les documents QT sont explicites que le qtcpsocket ne doit pas être utilisé de fils d'accrocs. I.E, créez un qtcpsocket dans le fil principal et faites attacher le signal à un objet dans un autre thread.

Je suppose que vous implémentez quelque chose comme un serveur Web où l'écoute crée un qtcpsocket sur l'acceptation. Vous voulez alors un autre fil de traitement de la tâche de traitement de cette prise. Vous ne pouvez pas.

La façon dont j'ai travaillé autour de cela est que j'ai gardé la prise dans le fil, elle est née. J'ai réparé toutes les données entrantes dans ce fil et jeté dans une file d'attente où un autre fil pouvait fonctionner sur ces données.

Vide virtuel Incomingconnection (QItPtr SocketDescriptor) < / a>

Remarque: Si une autre prise est créée dans la réimplémentation de cette méthode, elle doit être ajoutée au mécanisme de connexions en attente en appelant addPendingConnection () . .

Remarque: Si vous souhaitez gérer une connexion entrante sous la forme d'un nouvel objet qtcpsocket dans un autre thread, vous devez Passer le socketDescriptor à l'autre fil et créez L'objet qtcpsocket là-bas et utilisez son setsocketDescriptor () méthode.


5 commentaires

1
votes

Ce que j'ai lu dans le docs est celui Qtcpsocket ne doit pas être utilisé sur les threads. Si vous souhaitez l'utiliser dans un autre thread DOCS DOCS, vous devez créer une nouvelle instance QTcpsocket dans votre thread et définir le descripteur de la nouvelle instance. Pour ce faire, vous devez réimplément qtcpserver et utiliser Qtcpserver :: IncomingConnection . Un exemple simple est fourni ici .


0 commentaires

6
votes

Il est important de noter ce que vous pouvez et ne pouvez pas faire en termes de filetage qtcpsocket :

  • vous peut l'utiliser dans un fil non principal, mais seulement le fil dans lequel il a été créé.

  • vous ne peut pas Appeler différentes fonctions sur le qtcpsocket à partir de différents threads, par ex. Lisez dans un fil, écrivez-vous dans l'autre. Au lieu de cela, vous pouvez créer un fil séparé pour chaque qtcpsocket , ce qui les empêche d'utiliser du temps et des ressources pouvant peindre vos widgets dans le fil principal.

    imo, mettez votre Io, y compris qtcpsocket dans un fil autre que le thread principal est une meilleure pratique et doit-le faire pour toute application performante. J'utilise qtcpsocket dans des threads non principaux tout le temps à l'aide de l'idiome suivant: xxx

    m_thread est membre Fil (essentiellement simplement en veillant à ce qu'il ait une durée de vie supérieure à la portée actuelle) et m_concurrentqueue est une file d'attente de fil-sécurité ou std conteneur avec la protection mutex.

    Vous voudrez également connecter un signal (j'appelle habituellement cela joinall ) à la fonction de démission de la boucle d'événement et l'appelez à partir du destructeur de classe. Lorsque vous utilisez un idiome d'événement-boucle-in-a-fil, vous devez toujours faire attention à vous assurer de pouvoir détruire la classe correctement, sinon votre programme ne quitte pas (ou sous Windows, il sera terminé, généralement avec certains destructeurs. Ne pas être appelé, et cela finit par être une erreur silencieuse).

    I Utilisez également une variable de condition pour attendre après avoir créé le fil jusqu'à la démarrage de la boucle d'événement. Ce n'est pas nécessaire, mais si vous mettez ces threads ensemble dans des constructeurs, cela peut aider à rendre le flux de programme a plus de sens.


4 commentaires

Merci pour votre réponse. J'ai déjà évoqué le jour où vous avez posté. J'avais trouvé ce fait que ce fait que le qtcpsocket ou qwebsocket ne sont pas thread-mobiles! Ont soulevé un bug à QT à cet égard et la mettre sous la question ci-dessus.


@Nicolas, cette solution a l'air géniale mais je blessais comment gérer les données de m_concurrentqueue dans le fil principal, je veux dire devrais-je utiliser qticer ou simplement signaler pour notifier le fil principal pour démarrer la poignée Données en files d'attente? Quelle variante est la meilleure en termes de performance? Merci.


Y a-t-il une raison pour laquelle vous utilisez une lambda pour eventLoop.quit au lieu de & qeventloop :: Quitter ?


@cdgraham Je ne pense pas que cela a probablement copié de quelque chose qui a fait un certain nettoyage à la sortie.