2010-05-12 19 views
15

Mam wątek, który generuje pewne dane (lista pytonów) i który będzie dostępny dla widgetu, który odczyta i wyświetli dane w głównym wątku. Właściwie używam QMutex w celu zapewnienia dostępu do danych, w ten sposób:Komunikacja między wątkami w 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) 

Należy pamiętać, że nie jestem przekazując dane w emit() jak są dane generyczne (próbowałem użyć jako PyObject typ danych, ale podwójny free() spowodowałby awarię programu), ale kopiuję dane za pomocą deepcopy() (zakładając, że dane mogą być kopiowane w ten sposób). użyłem deepcopy(), ponieważ myślę, że kod jak:

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

by skopiować tylko odniesienie do danych (? Po prawej), a dane będą udostępniane i odblokowane po powrocie ... Czy to kod poprawny? Co mogę zrobić, jeśli dane są naprawdę duże (jak lista 1 000 000 artykułów)?

Dzięki.

P.S. Widziałem kilka przykładów, takich jak Qt Mandelbrot example lub threading example with PyQt, ale używają QImage jako parametru w gniazdach.

+0

Btw, myślę, że jest to wada tutaj: Ten kod może działać, ponieważ slowly_produce_data() zwraca wszystkie dane naraz, a następnie przypisuje je do zmiennej obiektu. Żaden muteks nie jest używany, ponieważ odniesienie do danych jest ustawiane na raz (i myślę, że jest bezpieczny), ale jeśli dane były produkowane w pętli i budowane w sekwencji (tj. Nie z powrotu), wówczas wymagany był również muteks. – AkiRoss

Odpowiedz

15

Myślę, że to powinno działać z PySide. jeśli nie działa zgłoś błąd na PySide Bugzilla (http://bugs.openbossa.org/) z małego testu:

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) 
Powiązane problemy