2010-01-20 4 views
5

J'essaie actuellement de réseauter avec Python asyncore et pyqt4.QObject (QPlainTextEdit) et problèmes de multithread

J'ai codé un petit serveur, qui écoute essentiellement sur certains ports, et renvoie tous les messages qu'il reçoit à l'expéditeur.

Depuis deux pintes QApplication.exec_() et asyncore.loop() sont des fonctions qui ne reviennent jamais je ne pouvais pas les lancer à la fois dans un thread, donc je regardé fixement asyncore.loop() dans un thread démon séparé.

Chaque fois que ma classe de serveur (dérivé de asyncore.dispatcher) établit ou supprime une connexion, ou envoie/reçoit un message, il appelle des méthodes de ma classe de fenêtre (dérivée de QtGui.QMainWindow), qui affiche les informations dans un QPlainTextEdit.

Mais le texte n'est pas visible, sauf si vous marquez le texte avec la souris.

console Python affiche suivantes msg d'erreur:

QObject::connect: Cannot queue arguments of type 'QTextBlock' 
(Make sure 'QTextBlock' is registered using qRegisterMetaType().) 
QObject::connect: Cannot queue arguments of type 'QTextCursor' 
(Make sure 'QTextCursor' is registered using qRegisterMetaType().) 

je lis sur certains forum, que cela peut être dû en appelant qt-fonctions d'un autre fil, et en utilisant des signaux & emplacements au lieu d'appeler la fonction simple peut résoudre le problème, mais j'ai essayé des signaux aussi, et j'ai toujours cette erreur.

Donc, (si c'est vraiment la cause de mes problèmes) quelle est la bonne façon d'appeler les méthodes d'un objet qt d'un autre thread?

EDIT Plus d'info: le asyncore.loop() est situé dans le fil de l'enfant, bien son blocage pas vraiment, mais seulement pendant l'exécution de asyncore.loop() ma classe Server (asyncore.dispatcher) peut faire du réseautage. Donc, pendant l'exécution de asyncore.loop() les méthodes de ma classe Server sont appelées par asyncore.loop() (= thread fils), et dans ces essayé d'émettre des signaux à la classe de fenêtre en cours d'exécution dans le thread principal

EDIT: on dirait que je l'ai eu à travailler maintenant, j'ai eu quelques erreurs dans mon code, tout fonctionne comme prévu avec des signaux maintenant.

EDIT: petit exemple: http://paste2.org/p/635612 (lien mort)

+0

Pouvez-vous publier une explication ou un extrait de la solution de travail? Cela aiderait sûrement les autres avec le même problème à l'avenir. =) –

Répondre

8

Il semble que vous essayez d'accéder à des classes QtGui d'un autre thread que le thread principal. Comme dans d'autres boîtes à outils GUI (par exemple Java Swing), cela n'est pas autorisé. De la Threads and QObjects page Web:

Bien que QObject est rentrante, l'interface graphique classes, notamment QWidget et toutes ses sous-classes , ne sont pas rentrants. Ils ne peuvent être utilisés qu'à partir du thread principal.

Une solution consiste à utiliser des signaux et des fentes pour la communication entre le fil principal (où les objets d'interface graphique en direct) et le filetage secondaire (s). Fondamentalement, vous émettez des signaux dans un thread qui sont livrés aux QObjects via l'autre thread. La page que j'ai liée à ci-dessus a une bonne discussion de ceci. En fait, toute la section sur Thread Support in Qt est une bonne lecture.Un problème potentiel que vous pourriez rencontrer est que, normalement, pour obtenir la prise en charge complète des signaux et des slots sur les threads, vous devez démarrer une boucle d'événement dans le thread fils en utilisant QThread::exec() (ou l'équivalent PyQt) pour que les signaux puissent être livré aux slots dans les QObjects qui y vivent. Dans votre cas, il semble que vous appelez asyncore.loop(), ce qui vous empêchera de le faire. Mais, si vous avez seulement besoin d'émettre des signaux dans une direction (du thread fils aux widgets dans le thread principal), je ne pense pas que vous aurez un problème.

+1

Les messages d'erreur indiquent qu'il tente d'établir une connexion signal/emplacement. Cependant, le type de données QTextBlock n'est pas un QMetaType enregistré et ne peut donc pas être transporté par des connexions entre threads. – e8johan

+0

J'ai complètement oublié d'essayer QThread ... mais comment puis-je utiliser QThreads pour mon problème ??, puisque la méthode QThreads 'exec() _' est une méthode de blocage, donc je ne peux pas l'exécuter dans le même thread .
@ e8johan: j'ai reçu les mêmes messages d'erreur quand je n'ai pas utilisé de signaux .. – smerlin