qt提供了許多用於處理執行緒的類和函式。 以下是qt程式設計師可以用來實現多執行緒應用程式的四種不同方法。
qthread
是qt中所有執行緒控制的基礎。 每個qthread
例項表示並控制乙個執行緒。
qthread
可以直接例項化或派生子類。 例項化qthread
提供了乙個並行事件迴圈,允許在輔助線程中觸發qobject
的slots
。 繼承qthread
則允許應用程式在啟動其事件迴圈之前初始化新執行緒,或者在沒有事件迴圈的情況下執行並行**。
class testthread : public qthread
;void testthread::run()
int main(int argc, char *argv)
經常建立和銷毀執行緒可能非常的耗費資源。 為了減少這種開銷,可以重用現有的執行緒來執行新的任務。qthreadpool
是可重用的qthreads
的集合,用來管理並重新利用qthreads
。
要在qthreadpool
所管理的的執行緒之一中執行**,需要繼承qrunnable
並重新實現qrunnable::run()
。 然後使用qthreadpool::start()
將剛剛實現的qrunnable
放入qthreadpool
的執行佇列中。 當qthreadpool
中存在空閒的執行緒時,qrunnable::run()
中的**將在該執行緒中執行。
每個qt應用程式都有乙個全域性執行緒池,可通過qthreadpool::globalinstance()
訪問。 此全域性執行緒池根據cpu中的核心數量自動維護最佳執行緒數。 不過我們仍然可以顯式建立和管理乙個的qthreadpool
。
class testtask : public qrunnable
};testtask *test =
new testtask();
// qthreadpool 持有test物件並自動delete
qthreadpool::globalinstance()->start(test);
qt concurrent
模組提供了處理一些常見平行計算模式的高階函式:
與使用qthread
和qrunnable
不同,這些功能不需要使用低階執行緒原語,如互斥鎖或訊號量。相反,它們返回乙個qfuture
物件,可用於在功能準備就緒時檢索結果。qfuture
也可用於查詢執行進度並暫停/恢復/取消執行。為方便起見,qfuturewatcher
通過訊號和槽實現與qfutures
的互動。
qt concurrent
的map
,filter
和reduce
演算法會自動將計算分配到所有可用的處理器核心中,因此現在編寫的應用程式在以後部署在具有更多cpu核的的系統上時仍然能充分利用硬體。
該模組還提供了qtconcurrent::run()
函式,該函式可以在另乙個執行緒中執行任何函式。但是,qtconcurrent::run()
僅對map
,filter
,reduce
提供部分支援。qfuture
可用於檢索函式的返回值並檢查執行緒是否正在執行。但是,對qtconcurrent::run()
的呼叫只使用乙個執行緒,不能暫停/恢復/取消,並且無法查詢進度。
這得通過另一篇文章說明了,詳見qt concurrent詳解
rectangle
workerscript
mousearea )}}
workerscript.onmessage = function(message) )
}
如上所述,qt為開發多執行緒應用程式提供了不同的解決方案。 給定應用程式的正確解決方案取決於新執行緒的目的和執行緒的生命週期。 以下是qt的多執行緒技術比較,接下來會針對某些示例用例的推薦解決方案。
特色qthread
qrunnable 和 qthreadpool
qtconcurrent::run()
qt concurrent (map, filter, reduce)
qt concurrent (map, filter, reduce)
language
c++c++
c++c++
qml可設定執行緒優先順序
yesyes
執行緒可以處理乙個事件迴圈
yes執行緒可以從訊號中獲取資料更新
yes(通過乙個worker
物件)
yes(由workerscript
獲得)
執行緒可以用訊號控制
yes(由qthread
獲得)
yes (通過qfuturewatcher
獲得)
執行緒可以被qfuture
監測
部分yes
天生具有暫停/恢復/取消的功能
yes生命週期
操作解決方案
一次呼叫
在另乙個執行緒中執行乙個新的函式,在執行期間可以獲取進度。
qt提供不同的解決方案派生qthread
並重新實現qthread::run()
然後啟動。並且發出進度更新的訊號。派生qrunnable:run()
,並使用qthreadpool::globalinstance()->start(qrunnable)
來執行。 將進度寫入乙個執行緒安全的變數來給外部進度資訊。使用qtconcurrent::run()
執行函式。 將進度寫入乙個執行緒安全的變數來給外部進度資訊。
一次呼叫
在另乙個執行緒中執行乙個現有函式並獲取其返回值。
使用qtconcurrent::run()
執行函式。 當函式返回時,讓qfuturewatcher
發出finished()
訊號,然後呼叫qfuturewatcher::result()
來獲取函式的返回值。
一次呼叫
使用所有可用的核心對容器的所有專案執行操作。 例如,從影象列表中生成縮圖。
一次呼叫/持久執行
在純qml應用程式中執行耗時計算,並在結果準備好時更新gui。
將計算**放在.js
指令碼中並將其附加到workerscript
例項。 呼叫sendmessage()
以在新執行緒中啟動計算。 讓指令碼也呼叫workerscript::sendmessage()
,將結果傳遞歸gui執行緒。 在onmessage
中處理結果並在那裡更新gui。
持久執行
讓乙個物件在另乙個執行緒中生存,可以根據請求執行不同的任務,並且/或者可以接收新的資料來處理
子類化qobject
以建立乙個工作者(worker
)。 例項化這個工作物件和乙個qthread
。 將工作物件移至新執行緒(運用movetothread
)。 通過佇列的訊號-槽連連線(queued signal-slot connections
,connect
函式的最後乙個引數)向工作物件傳送命令或資料。
持久執行
在另乙個執行緒中重複執行耗時的操作,執行緒不需要接收任何訊號或事件。
子類話qthread
並重新實現qthread::run()
,直接寫入無限迴圈。 在沒有事件迴圈的情況下啟動執行緒。 讓執行緒發出訊號將資料傳送回gui執行緒。
持久執行
生存在另乙個執行緒中的物件,執行諸如輪詢埠等重複的任務並與gui執行緒通訊。
同上,但是在工作執行緒中使用乙個定時器來輪詢。儘管如此,處理輪詢的最好的解決方案是徹底避免它。有時qsocketnotifer
是乙個替代。
Qt中的多執行緒程式設計
qt中的多執行緒程式設計 qthread 類,該類提供了建立乙個新執行緒以及控制線程執行的各種方法。執行緒是通過 qthread run 過載函式開始執行的 在 qt 系統中,始終執行著乙個gui 主事件執行緒,這個主線程從視窗系統中獲取事件,並將它們分發到各個元件去處理。在 qthread 類中還...
Qt 中的多執行緒 二
可重入與執行緒安全 在qt文件中,術語 可重入 與 執行緒安全 被用來說明乙個函式如何用於多執行緒程式。假如乙個類的任何函式在此類的多個不同的例項上,可以被多個執行緒同時呼叫,那麼這個類被稱為是 可重入 的。假如不同的執行緒作用在同乙個例項上仍可以正常工作,那麼稱之為 執行緒安全 的。大多數c 類天...
Qt 中的多執行緒 二
可重入與執行緒安全 在qt文件中,術語 可重入 與 執行緒安全 被用來說明乙個函式如何用於多執行緒程式。假如乙個類的任何函式在此類的多個不同的例項上,可以被多個執行緒同時呼叫,那麼這個類被稱為是 可重入 的。假如不同的執行緒作用在同乙個例項上仍可以正常工作,那麼稱之為 執行緒安全 的。大多數c 類天...