PyQt5學習筆記15----PyQt 線程相關類,pyqt515----pyqt
QThread是我們將要詳細介紹的第一個類。它也是 Qt 線程類中最核心的底層類。由於 PyQt 的跨平台特性,QThread要隱藏掉所有平台相關的代碼。
正如前面所說,要使用QThread開始一個線程,我們可以建立它的一個子類,然後覆蓋其QThread.run()函數:
class Thread(QThread): def __init__(self): super(Thread,self).__init__() def run(self): pass #線程相關代碼
然後我們這樣建立一個新的線程
thread=Thread()thread.start()
這個預設實現其實是簡單地調用了QThread.exec()函數,而這個函數,按照我們前面所說的,其實是開始了一個事件迴圈
QRunnable是我們要介紹的第二個類。這是一個輕量級的抽象類別,用於開始一個另外線程的任務。這種任務是運行過後就丟棄的。由於這個類是抽象類別,我們需要繼承QRunnable,然後重寫其純虛函數QRunnable.run():
class Task(QRunnable): def __init__(self): super(QRunnable,self).__init__() def run(self): pass #線程相關代碼
要真正執行一個QRunnable對象,我們需要使用QThreadPool類。顧名思義,這個類用於管理一個線程池。通過調用QThreadPool.start(runnable)函數,我們將一個QRunnable對象放入QThreadPool的執行隊列。一旦有線程可用,線程池將會選擇一個QRunnable對象,然後在那個線程開始執行。所有 PyQt 應用程式都有一個全域線程池,我們可以使用QThreadPool.globalInstance()獲得這個全域線程池;與此同時,我們也可以自己建立私人的線程池,並進行手動管理。
task=Task()QThreadPool.globalInstance().start(task)
需要注意的是,QRunnable不是一個QObject,因此也就沒有內建的與其它組件互動的機制。為了與其它組件進行互動,你必須自己編寫低級線程原語,例如使用 mutex 守護來擷取結果等。
QtConcurrent是我們要介紹的最後一個對象。這是一個進階 API,構建於QThreadPool之上,用於處理大多數通用的並行計算模式:map、reduce 以及 filter。它還提供了QtConcurrent.run()函數,用於在另外的線程運行一個函數。注意,QtConcurrent是一個命名空間而不是一個類,因此其中的所有函數都是命名空間內的全域函數。
不同於QThread和QRunnable,QtConcurrent不要求我們使用低級同步原語:所有的QtConcurrent都返回一個QFuture對象。這個對象可以用來查詢當前的運算狀態(也就是任務的進度),可以用來暫停/回複/取消任務,當然也可以用來獲得運算結果。注意,並不是所有的QFuture對象都支援暫停或取消的操作。比如,由QtConcurrent.run()返回的QFuture對象不能取消,但是由QtConcurrent.mappedReduced()返回的是可以的。QFutureWatcher類則用來監視QFuture的進度,我們可以用訊號槽與QFutureWatcher進行互動(注意,QFuture也沒有繼承QObject)。
下面我們可以對比一下上面介紹過的三種類:
特性 |
QThread |
QRunnable |
QtConcurrent |
進階 API |
✘ |
✘ |
|
面向任務 |
✘ |
|
|
內建對暫停/恢複/取消的支援 |
✘ |
✘ |
|
具有優先順序 |
|
✘ |
✘ |
可運行事件迴圈 |
|
✘ |
✘ |