2010-12-01 11 views
5

Tengo algunos problemas para comunicarme entre subprocesos en PyQt. Estoy usando señales para comunicarme entre dos hilos, un emisor y un oyente. El remitente envía mensajes, que se espera sean recibidos por el oyente. Sin embargo, no se reciben mensajes. ¿Alguien puede sugerir lo que podría estar yendo mal? Estoy seguro de que debe ser algo simple, pero he estado buscando durante horas y no he encontrado nada. ¡Gracias por adelantado!Problema de subprocesamiento y señales en PyQt

from PyQt4 import QtCore,QtGui 
import time 

class Listener(QtCore.QThread):  
    def __init__(self): 
     super(Listener,self).__init__() 

    def run(self): 
     # just stay alive, waiting for messages 
     print 'Listener started' 
     while True: 
      print '...' 
      time.sleep(2) 

    def say_hello(self): 
     print ' --> Receiver: Hello World!' 

class Sender(QtCore.QThread): 
    # a signal with no arguments 
    signal = QtCore.pyqtSignal() 

    def __init__(self): 
     super(Sender,self).__init__() 
     # create and start a listener 
     self.listener = Listener() 
     self.listener.start() 
     # connect up the signal 
     self.signal.connect(self.listener.say_hello) 
     # start this thread 
     self.start() 

    def run(self): 
     print 'Sender starting' 
     # send five signals 
     for i in range(5): 
      print 'Sender -->' 
      self.signal.emit() 
      time.sleep(2) 
     # the sender's work is done 
     print 'Sender finished' 
+0

Qt decide por cuál de ellos para enviar una señal al dependiendo de qué hilo creado la instancia del objeto de la señal está en. Es decir, si se crea un objeto de escucha de su hilo principal y enviar señales a ella, que va a invocarlos en el hilo principal. Recuerde, el objeto no es el hilo. Ver p. ftp://ftp.qt.nokia.com/videos/DevDays2007/DevDays2007%20-%20Multi-threading_in_Qt.pdf para obtener más información sobre "afinidad de subprocesos" en Qt. –

Respuesta

5

No estoy seguro de si eso es lo que necesita, pero funciona bien ...

from PyQt4 import QtCore,QtGui 
import time 

class Listener(QtCore.QThread): 
    def __init__(self): 
     super(Listener,self).__init__() 

    def run(self): 
     print('listener: started') 
     while True: 
      time.sleep(2) 

    def connect_slots(self, sender): 
     self.connect(sender, QtCore.SIGNAL('testsignal'), self.say_hello) 

    def say_hello(self): 
     print('listener: received signal') 

class Sender(QtCore.QThread): 
    def __init__(self): 
     super(Sender,self).__init__() 

    def run(self): 
     for i in range(5): 
      print('sender: sending signal') 
      self.emit(QtCore.SIGNAL('testsignal')) 
      time.sleep(2) 
     print('sender: finished') 

if __name__ == '__main__': 
    o_qapplication = QtGui.QApplication([]) 
    my_listener = Listener() 
    my_sender = Sender() 
    my_listener.connect_slots(my_sender) 
    my_listener.start() 
    my_sender.start() 
    i_out = o_qapplication.exec_() 
4

El problema es que una QThread para enviar señales/receptor, que debe estar en ejecución un EventLoop. No lo eres, por lo que no hay oportunidad para que el hilo responda. Echa un vistazo a esta publicación en el blog: You're doing it wrong

He aquí un ejemplo que funciona para mí: ten en cuenta que debes llamar a moveToThread ANTES de conectar las señales (esto no se mencionó en el blog, no estoy seguro si es específico de PyQt) de lo contrario, se ejecutarán en el hilo principal.

import sys 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
import time 

class MyThread(QThread): 
    def __init__(self, name): 
     super(MyThread, self).__init__() 
     self.setObjectName(name) 

    def run(self): 
     print "RUN", QThread.currentThread().objectName(), QApplication.instance().thread().objectName() 
     self.exec_() 
     print "RUN DONE", QThread.currentThread().objectName() 

class Producer(QObject): 
    def __init__(self, parent=None): 
     super(Producer, self).__init__(parent) 

    def Start(self): 
     for i in range(5): 
      print "Producer",i,QThread.currentThread().objectName() 
      self.emit(SIGNAL("testsignal"),i) 
      time.sleep(2) 
     time.sleep(1) 
     qApp.quit() 

class Consumer(QObject): 
    def __init__(self, parent=None): 
     super(Consumer, self).__init__(parent) 

    def Consume(self, i): 
     print "Consumed",i,QThread.currentThread().objectName() 

if __name__ == "__main__": 
    app = QApplication([]) 
    producer = Producer() 
    consumer = Consumer() 
    QThread.currentThread().setObjectName("MAIN") 
    producerThread = MyThread("producer") 
    consumerThread = MyThread("consumer") 
    producer.moveToThread(producerThread) 
    consumer.moveToThread(consumerThread) 
    producerThread.started.connect(producer.Start) 
    producer.connect(producer, SIGNAL("testsignal"), consumer.Consume) 
    def aboutToQuit(): 
     producerThread.quit() 
     consumerThread.quit() 
     time.sleep(1) 
    qApp.aboutToQuit.connect(aboutToQuit) 
    consumerThread.start() 
    time.sleep(.1) 
    producerThread.start() 
    sys.exit(app.exec_())