I have a thread which produces some data (a python list) and which shall be available for a widget that will read and display the data in the main thread. Actually, I'm using QMutex to provide access to the data, in this way:
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)
Note that I'm not passing the data in the emit()
as they are generic data (I tried to use PyObject as data type, but a double free()
would crash the program), but I'm copying the data with a deepcopy()
(assuming the data can be copied like this).
I used a deepcopy() because I guess that a code like:
def get_data(self):
QMutexLock(self.mutex)
return self.data
would only copy a reference to the data (right?) and data would be shared AND unlocked after the return... Is this code correct? What can I do if data are really large (like a list of 1'000'000 items)?
Thanks.
P.S. I saw some examples, like the Qt Mandelbrot example, or the threading example with PyQt, but they use QImage as parameter in the slots.
Perhaps the safest way to send data from one thread to another is to use a Queue from the queue library. To do this, create a Queue instance that is shared by the threads. Threads then use put() or get() operations to add or remove items from the queue as shown in the code given below.
Threads of the same process can communicate with each other through synchronization primitives like locks and semaphores, events like wait and notify, or through shared memory. The following illustration shows how a process (single-threaded) and a multi-threaded process share memory.
Python MultithreadUsing Event objects is the simple way to communicate between threads. An Event manages an internal flag that callers can either set() or clear(). Other threads can wait() for the flag to be set(). Note that the wait() method blocks until the flag is true.
I think this should work with PySide. if not work please report a bug on PySide bugzilla(http://bugs.openbossa.org/) with a small test case:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With