2010-05-12 188 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)