QT QThread 多線程操作

在QT中,QT應用程序所在的線程爲主線程,也稱爲“GUI線程”,QT GUI必須運行在此線程上;而非主線程稱爲“工作者線程”,主要處理從主線程中卸下的一些工作,例如數據的同步訪問等。需要明確的是,同一個進程的不同線程之間共享相同的地址空間。

 

什麼時候應該使用線程?

     如果一個應用程序需要處理一些耗時的數據計算時,應該用一個獨立線程來做這些運算,這樣用戶可以提前中斷或者暫停數據處理的工作,或者做一些和數據計算無關的工作,從而保證GUI線程或其他對時間敏感的線程保持良好的反應速度。

 

多線程使用的風險?

      使用多線程最需要小心的就是共享數據的變動,存在於不同線程的變量很有可能被修改,難以確保其一致性

 

QT線程技術

線程生命週期                 操作             解決方案
單次週期 在新的線程中運行一個新的線性函數,且在運行期間可以更新進度
  • 將函數在 QThread::run() 中重新實現,並啓動 QThread 。通過發射信號更新進度。
  • 將函數在 QThread::run() 中重新實現,並將 QRunnable 加入一個 QThreadPool 。寫一個線程安全變量用於更新進度。
  • 使用 QtConcurrent::run() 運行函數。寫一個線程安全變量用於更新進度
單次週期 在新的線程中運行一個已經存在的函數,並得到其返回值 使用 QtConcurrent::run() 運行函數。當函數有返回值時, QFutureWatcher 會發送 finished() 信號,並調用 QFutureWatcher::result() 獲得函數返回值。
單次週期 需要操作一個容器中所有的項,執行過程中使用所有可用的核,如從圖像列表中生成縮略圖 使用 Qt Concurrent 的 QtConcurrent::filter() 選擇包含的元素, QtConcurrent::map() 將會把操作應用到所選的每個元素。要將輸出摺疊到一個信號結果,使用QtConcurrent::filteredReduced() 和 QtConcurrent::mappedReduced() 作爲替代。
常駐 有一個對象位於另一個線程中,將讓其根據不同的請求執行不同的操作,即線程之間需要進行必要的通信。 從QObject派生一個類實現必要的槽和信號,將對象移到一個具有事件循環的線程中,並通過Queued信號與對象進行通信
常駐 對象位於另一個線程中,對象不斷執行重讀的任務如輪詢某個端口,並與GUI線程進行通信 與上述類似,但同時在工作者線程中使用一個計時器來實現輪詢,或者使用QSocketNotifilter

eg:如果QThread是在ui所在的線程裏生成,那麼QThread的其他非run函數都是和ui線程一樣,故這些函數應該儘量不要有太耗時的操作,而是應該將所有耗時操作放到run函數中實現。

注意:如果在QThread的非run函數中有對QThread的某個變量進行變更,且該變量在run函數中也被用到,那需要注意上鎖的問題,因爲有可能該變量在前幾毫秒就被run調用過導致值被修改。

 

QT中使用線程的方法有兩種

1、使用繼承於QThread的線程 

     QThread 只有run函數是在新線程裏,而其他函數都在舊線程內,Start()方法函數創建了一個新的線程並在新線程中調用重載的run()方法,因此run函數一般都需要重寫。而wait()方法被調用用來阻塞調用的線程直到run方法執行完畢。

     exec()和靜態方法usleep(),msleep()和sleep()應該在新創建的線程中調用

2、繼承QObject的多線程實現

     一個線程的事件循環爲駐足在該線程中的所有QObjects派發了所有事件,其中包括了在這個線程中創建的所有對象。或是移植到這個線程中的對象。

     QObject的線程親和性

          QObject對象有一個線程親和性,即其生存在某個特定的線程中。當一個QObject對象接收到一個signal或者一個posted event時,相應的槽函數或事件處理器會在該對象所生存的線程中執行;反之如果其生存的線程沒有運行事件循環,那麼它將不能接收到signal或者event。

         默認情況下,QObject對象生存在創建它的那個線程中,但是我們可以使用thread()函數來查詢對象的線程親和性,並且可以使用moveToThread()來改變一個對象的線程親和性。需要注意的是,所有對象都應該和它的父對象生存在同一個線程中。因此MoveToThread()在有父級的時候會失敗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章