2010-05-12 27 views
15

Tôi có một luồng tạo ra một số dữ liệu (danh sách python) và sẽ có sẵn cho một tiện ích sẽ đọc và hiển thị dữ liệu trong chuỗi chính. Thực ra, tôi đang sử dụng QMutex để cung cấp quyền truy cập vào các dữ liệu, theo cách này:Giao tiếp giữa các chủ đề trong 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) 

Lưu ý rằng tôi không đi qua các dữ liệu trong emit() như họ đang có dữ liệu chung (tôi cố gắng sử dụng PyObject như loại dữ liệu, nhưng một đôi free() sẽ sụp đổ chương trình), nhưng tôi đang sao chép dữ liệu với một deepcopy() (giả sử dữ liệu có thể được sao chép như thế này). tôi đã sử dụng một deepcopy() bởi vì tôi đoán rằng một mã như:

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

sẽ chỉ sao chép một tham chiếu đến dữ liệu (? Bên phải) và dữ liệu sẽ được chia sẻ và mở khóa sau khi trở về ... Đây có phải là mã đúng? Tôi có thể làm gì nếu dữ liệu thực sự lớn (như danh sách các mục 1'000'000)?

Cảm ơn.

P.S. Tôi thấy một số ví dụ, chẳng hạn như Qt Mandelbrot example hoặc threading example with PyQt, nhưng chúng sử dụng QImage làm thông số trong các vị trí.

+0

Btw, tôi nghĩ có một lỗ hổng ở đây: mã này có thể hoạt động vì slowly_produce_data() trả về tất cả dữ liệu cùng một lúc, và sau đó gán cho một biến đối tượng. Không có mutex được sử dụng bởi vì tham chiếu dữ liệu được đặt cùng một lúc (và tôi nghĩ là an toàn), nhưng nếu dữ liệu được tạo ra trong vòng lặp và được xây dựng theo thứ tự (nghĩa là không trả về), thì cũng cần có một mutex. – AkiRoss

Trả lời

15

Tôi nghĩ rằng điều này sẽ làm việc với PySide. nếu không hoạt động, hãy báo cáo lỗi trên PySide bugzilla (http://bugs.openbossa.org/) với một trường hợp thử nghiệm nhỏ:

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) 
Các vấn đề liên quan