2010-05-12 143 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 examplethreading example with PyQt,但它们使用QImage作为插槽中的参数。

+0

,我认为这里有一个缺陷:该代码可以正常工作,因为slowly_produce_data()一次返回所有数据,然后分配给一个对象变量。因为数据引用一次被设置(我认为是安全的),所以没有使用互斥锁,但是如果数据是在循环中生成的,并且是按顺序构建的(即不是从返回中),那么也需要互斥锁。 – AkiRoss 2010-11-20 22:57:04

回答

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)