2010-05-12 23 views
15

Tengo un hilo que produce algunos datos (una lista de python) y que estará disponible para un widget que leerá y mostrará los datos en el hilo principal. En realidad, estoy usando QMutex para proporcionar acceso a los datos, de esta manera:Comunicación entre hilos en PySide

class Thread(QThread): 
    def get_data(self): 
    QMutexLock(self.mutex) 
    return deepcopy(self.data) 

    def set_data(self, data): 
    QMutexLock(self.mutex) 
    self.data = deepcopy(data) 

    def run(self): 
    self.mutex = QMutex() 
    while True: 
     self.data = slowly_produce_data() 
     self.emit(SIGNAL("dataReady()")) 

class Widget(QWidget): 
    def __init__(self): 
    self.thread = Thread() 
    self.connect(self.thread, SIGNAL("dataReady()"), self.get_data) 
    self.thread.start() 

    def get_data(self): 
    self.data = self.thread.get_data() 

    def paintEvent(self, event): 
    paint_somehow(self.data) 

Tenga en cuenta que no estoy pasando los datos en el emit(), ya que son datos genéricos (He intentado utilizar como PyObject tipo de datos, pero un doble free() colgaría el programa), pero estoy copiando los datos con un deepcopy() (suponiendo que los datos se pueden copiar de esta manera). he usado un deepcopy() porque supongo que un código como:

def get_data(self): 
    QMutexLock(self.mutex) 
    return self.data 

sería copiar solamente una referencia a los datos (? Derecha) y los datos serían compartidos y desbloqueado después de la vuelta ... ¿Es esta código correcto? ¿Qué puedo hacer si los datos son realmente grandes (como una lista de 1'000'000 elementos)?

Gracias.

P.S. Vi algunos ejemplos, como el Qt Mandelbrot example, o el threading example with PyQt, pero usan QImage como parámetro en las ranuras.

+0

Por cierto, creo que hay una falla aquí: este código puede trabajar debido a que la slowly_produce_data() devuelve todos los datos a la vez, y luego se asigna a una variable de objeto. No se utiliza mutex porque la referencia de datos se establece de una vez (y creo que es seguro), pero si los datos se produjeron en el ciclo y se construyeron en secuencia (es decir, no a partir de un retorno), también se requirió un mutex. – AkiRoss

Respuesta

15

Creo que esto debería funcionar con PySide. si no funciona por favor, informar de un error en Bugzilla PySide (http://bugs.openbossa.org/) con un pequeño caso de prueba:

class Thread(QThread): 
    dataReady = Signal(object) 

    def run(self): 
    while True: 
     self.data = slowly_produce_data() 
     # this will add a ref to self.data and avoid the destruction 
     self.dataReady.emit(self.data) 

class Widget(QWidget): 
    def __init__(self): 
    self.thread = Thread() 
    self.thread.dataReady.connect(self.get_data, Qt.QueuedConnection) 
    self.thread.start() 

    def get_data(self, data): 
    self.data = data 

    def paintEvent(self, event): 
    paint_somehow(self.data)