2010-01-20 16 views
5

Actualmente estoy intentando aprender a trabajar en red con Python asyncore y pyqt4.QObject (QPlainTextEdit) y problemas de subprocesamiento múltiple

Codifiqué un pequeño servidor, que básicamente escucha en algún puerto, y reenvía todos los mensajes que recibe al remitente.

Dado que ambos cuartos de galón QApplication.exec_() y asyncore.loop() son funciones que no volver nunca que no a los dos podría comenzar en un hilo, así que miraron asyncore.loop() en un hilo de utilidad independiente.

Cada vez que mi clase de servidor (derivado de asyncore.dispatcher) establece o cae una conexión, o envía/recieves un mensaje, se llama a los métodos de mi clase de ventana (derivado de QtGui.QMainWindow), que muestra la información en una QPlainTextEdit.

Pero el texto no está visible, a menos que marque el texto con el mouse.

Python pantallas de la consola siguientes msg del error:

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().) 

He leído en algún foro, que esto puede ser causado por llamar qt-funciones desde otro hilo, y que el uso de señales & ranuras en lugar de llamar la función normal puede soluciona el problema, pero también he intentado con las señales, y sigo teniendo este error.

Entonces, (si esa es realmente la causa de mis problemas) ¿cuál es la forma correcta de llamar a los métodos de un objeto qt desde otro subproceso?

EDITAR Más información: la asyncore.loop() se encuentra en el hilo hijo, así que no es realmente el bloqueo, pero sólo durante el tiempo de ejecución de asyncore.loop() mi clase de servidor (asyncore.dispatcher) puede hacer redes. Entonces, durante el tiempo de ejecución de asyncore.loop() los métodos de mi clase Servidor SON llamados por asyncore.loop() (= hilo hijo), y en estos i intenté emitir señales a la clase de ventana que se ejecuta en el hilo principal

EDIT: Parece que lo tengo funcionando ahora, tuve algunos errores en mi código, todo funciona según lo previsto con las señales ahora.

EDIT: pequeño ejemplo: http://paste2.org/p/635612 (enlace no válido)

+0

¿Puede publicar una explicación o un fragmento de la solución de trabajo? Seguramente ayudaría a otros con el mismo problema en el futuro. =) –

Respuesta

8

Parece que está tratando de acceder a las clases QtGui de un hilo que no sea el hilo principal. Al igual que en algunos otros kits de herramientas de GUI (por ejemplo, Java Swing), eso no está permitido. Desde la página web Threads and QObjects:

Aunque QObject es reentrante, las clases de interfaz gráfica de usuario , en particular QWidget y todas sus subclases , no son reentrantes. Ellos solo pueden usarse desde el hilo principal.

Una solución es usar señales y ranuras para la comunicación entre el hilo principal (donde viven los objetos de la GUI) y sus hilos secundarios. Básicamente, usted emite señales en un hilo que se entregan a los QObjects a través del otro hilo. La página a la que he vinculado arriba tiene una buena discusión de esto. En realidad, toda la sección en Thread Support in Qt es una buena lectura. Un problema potencial que podría encontrar es que, normalmente, para obtener señales completas y soporte de ranuras trabajando en subprocesos, necesita iniciar un bucle de evento en la cadena secundaria usando QThread::exec() (o el equivalente PyQt) para que las señales puedan ser entregado a las máquinas tragamonedas en los QObjects que viven allí. En su caso, parece que está realizando una llamada de bloqueo al asyncore.loop(), lo que le impedirá hacerlo. Pero, si solo necesita emitir señales en una dirección (desde el hilo secundario hasta los widgets en el hilo principal), no creo que tenga un problema.

+1

Los mensajes de error indican que intenta realizar una conexión de señal/ranura. Sin embargo, el tipo de datos QTextBlock no es un QMetaType registrado y, por lo tanto, no puede ser transportado por conexiones entre hilos. – e8johan

+0

Me olvidé por completo de probar QThread ... pero ¿cómo puedo usar QThreads para mi Issue ??, ya que el método 'exec() _' de QThreads es un método de bloqueo nuevamente, así que no puedo ejecutarlo en el mismo hilo como mi clase de servidor .
@ e8johan: tengo los mismos mensajes de error cuando no uso señales. – smerlin

Cuestiones relacionadas