2010-05-12 4 views
15

У меня есть поток, который создает некоторые данные (список python) и которые должны быть доступны для виджета, который будет читать и отображать данные в основном потоке. На самом деле, я использую QMutex, чтобы обеспечить доступ к данным, таким образом:Связь между потоками в 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) 

Обратите внимание, что я не передавая данные в emit(), поскольку они являются общими данными (я пытался использовать PyObject, как тип данных, но двойной free() приведет к сбою программы), но я копирую данные с помощью deepcopy() (при условии, что данные могут быть скопированы следующим образом). я использовал DeepCopy(), потому что я думаю, что такой код:

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

будет только скопировать ссылку на данные (? Справа) и данные будут доступны и разблокирован после возвращения ... ли это код правильный? Что делать, если данные действительно большие (например, список из 1'000'000 элементов)?

Спасибо.

P.S. Я видел несколько примеров, например, Qt Mandelbrot example или threading example with PyQt, но они используют QImage в качестве параметра в слотах.

+0

Btw, я думаю, что есть недостаток здесь: этот код может работать, потому что slow_produce_data() возвращает все данные одновременно, а затем назначается переменной объекта. Мьютекс не используется, потому что ссылка на данные задается сразу (и я думаю, что это безопасно), но если данные были созданы в цикле и построены в последовательности (т. Е. Не из возврата), тогда там тоже был необходим мьютекс. – AkiRoss

ответ

15

Я думаю, что это должно работать с PySide. если не работает, пожалуйста, сообщите об ошибке на PySide Bugzilla (http://bugs.openbossa.org/) с помощью небольшого тестового примера:

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)