Связь между потоками в PySide
У меня есть поток, который создает некоторые данные (список python) и который будет доступен для виджета, который будет читать и отображать данные в основном потоке.
Фактически, я использую QMutex для обеспечения доступа к данным следующим образом:
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 Мандельброта или пример потоковой передачи с PyQt, но они используют параметр QImage как параметр в слотах.
Ответы
Ответ 1
Я думаю, что это должно работать с 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)