2010-05-12 6 views
15

Ich habe einen Thread, der einige Daten (eine Python-Liste) erzeugt und die für ein Widget verfügbar sein soll, das die Daten im Hauptthread lesen und anzeigen wird. versuchtenKommunikation zwischen Threads in 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) 

Beachten Sie, dass ich nicht die Daten in den emit() bin vorbei, da sie allgemeine Daten (I PyObject zu verwenden, wie: Eigentlich bin ich QMutex mit, um den Zugang zu den Daten, auf diese Weise Datentyp, aber ein Doppel free() würde das Programm zum Absturz bringen, aber ich kopiere die Daten mit einer deepcopy() (vorausgesetzt, die Daten können so kopiert werden). benutzen ich ein deep(), weil ich, dass ein Code erraten, wie:

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

nur einen Verweis auf die Daten kopiert werden würde (? Rechts) und Daten gemeinsam genutzt und entriegelt nach der Rückkehr würden ... Ist die Code richtig? Was kann ich tun, wenn die Daten wirklich groß sind (wie eine Liste von 1'000'000 Artikeln)?

Danke.

P.S. Ich sah einige Beispiele, wie die Qt Mandelbrot example, oder die threading example with PyQt, aber sie verwenden QImage als Parameter in den Slots.

+0

Btw, ich denke, ein Fehler gibt es hier: Dieser Code kann funktionieren, weil die language_produce_data() gibt alle Daten auf einmal zurück und wird dann einer Objektvariablen zugewiesen. Es wird kein Mutex verwendet, da die Datenreferenz sofort gesetzt wird (und ich denke, dass es sicher ist), aber wenn Daten in der Schleife erzeugt und in Folge aufgebaut wurden (d. H. Nicht von einer Rückkehr), dann wurde auch dort ein Mutex benötigt. – AkiRoss

Antwort

15

Ich denke, das sollte mit PySide funktionieren. wenn nicht, bitte einen Bug auf pyside Bugzilla (http://bugs.openbossa.org/) mit einem kleinen Testfall melden:

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)