1. 程式人生 > >Qt之執行緒和QObject

Qt之執行緒和QObject

前面兩個章節我們從事件迴圈和執行緒類庫兩個角度闡述有關執行緒的問題。本章我們將深入執行緒間得互動,探討執行緒和QObject之間的關係。在某種程度上,這才是多執行緒程式設計真正需要注意的問題。

現在我們已經討論過事件迴圈。我們說,每一個 Qt 應用程式至少有一個事件迴圈,就是呼叫了QCoreApplication::exec()的那個事件迴圈。不過,QThread也可以開啟事件迴圈。只不過這是一個受限於執行緒內部的事件迴圈。因此我們將處於呼叫main()函式的那個執行緒,並且由QCoreApplication::exec()建立開啟的那個事件迴圈成為主事件迴圈,或者直接叫主迴圈。注意,QCoreApplication::exec()

只能在呼叫main()函式的執行緒呼叫。主迴圈所在的執行緒就是主執行緒,也被成為 GUI 執行緒,因為所有有關 GUI 的操作都必須在這個執行緒進行。QThread的區域性事件迴圈則可以通過在QThread::run()中呼叫QThread::exec()開啟:

C++
12345678classThread:publicQThread{protected:voidrun(){/* ... 初始化 ... */exec();}};

記得我們前面介紹過,Qt 4.4 版本以後,QThread::run()不再是純虛擬函式,它會呼叫QThread::exec()

函式。與QCoreApplication一樣,QThread也有QThread::quit()QThread::exit()函式來終止事件迴圈。

執行緒的事件迴圈用於為執行緒中的所有QObjects物件分發事件;預設情況下,這些物件包括執行緒中建立的所有物件,或者是在別處建立完成後被移動到該執行緒的物件(我們會在後面詳細介紹“移動”這個問題)。我們說,一個QObject的執行緒依附性(thread affinity)是指它所在的那個執行緒。它同樣適用於在QThread的建構函式中構建的物件:

C++
1 2 3 4 5 6 7 8 9 10 11 12 13 classMyThread:publicQThread { public: MyThread() { otherObj=newQObject; } private: QObject obj; QObject*otherObj; QScopedPointer yetAnotherObj; };

在我們建立了MyThread物件之後,objotherObjyetAnotherObj的執行緒依附性是怎樣的?是不是就是MyThread所表示的那個執行緒?要回答這個問題,我們必須看看究竟是哪個執行緒建立了它們:實際上,是呼叫了MyThread建構函式的執行緒建立了它們。因此,這些物件不在MyThread所表示的執行緒,而是在建立了MyThread的那個執行緒中。

我們可以通過呼叫QObject::thread()可以查詢一個QObject的執行緒依附性。注意,在QCoreApplication物件之前建立的QObject沒有所謂執行緒依附性,因此也就沒有物件為其派發事件。也就是說,實際是QCoreApplication建立了代表主執行緒的QThread物件。

執行緒和QObject

我們可以使用執行緒安全的QCoreApplication::postEvent()函式向一個物件傳送事件。它將把事件加入到物件所在的執行緒的事件佇列中,因此,如果這個執行緒沒有執行事件迴圈,這個事件也不會被派發。

值得注意的一點是,QObject及其所有子類都不是執行緒安全的(但都是可重入的)。因此,你不能有兩個執行緒同時訪問一個QObject物件,除非這個物件的內部資料都已經很好地序列化(例如為每個資料訪問加鎖)。記住,在你從另外的執行緒訪問一個物件時,它可能正在處理所線上程的事件迴圈派發的事件!基於同樣的原因,你也不能在另外的執行緒直接delete一個QObject物件,相反,你需要呼叫QObject::deleteLater()函式,這個函式會給物件所線上程傳送一個刪除的事件。

此外,QWidget及其子類,以及所有其它 GUI 相關類(即便不是QObject的子類,例如QPixmap),甚至不是可重入的:它們只能在 GUI 執行緒訪問。

QObject的執行緒依附性是可以改變的,方法是呼叫QObject::moveToThread()函式。該函式會改變一個物件及其所有子物件的執行緒依附性。由於QObject不是執行緒安全的,所以我們只能在該物件所線上程上呼叫這個函式。也就是說,我們只能在物件所線上程將這個物件移動到另外的執行緒,不能在另外的執行緒改變物件的執行緒依附性。還有一點是,Qt 要求QObject的所有子物件都必須和其父物件在同一執行緒。這意味著:

  • 不能對有父物件(parent 屬性)的物件使用QObject::moveToThread()函式
  • 不能在QThread中以這個QThread本身作為父物件建立物件,例如:
    C++
    12345classThread:

    相關推薦

    Qt執行QObject

    前面兩個章節我們從事件迴圈和執行緒類庫兩個角度闡述有關執行緒的問題。本章我們將深入執行緒間得互動,探討執行緒和QObject之間的關係。在某種程度上,這才是多執行緒程式設計真正需要注意的問題。 現在我們已經討論過事件迴圈。我們說,每一個 Qt 應用程式至

    python執行程序

    1.建立執行緒 –執行緒 –程序 —一個程序裡面必定會有一個主執行緒 python執行緒的模組 2._thread 模組中建立多執行緒 import _thread import threading import time def job(name): print(“這是

    Java多執行-併發執行程序的區別

    執行緒和程序的區別 答: 程序是一個“執行中的程式”,是系統進行資源分配和排程的一個獨立單位 執行緒是程序的一個實體,一個程序中擁有多個執行緒,執行緒之間共享地址空間和其他資源(所以通訊和同步等操作執行緒比程序更加容易) 執行緒上下文的切換比程序上下文切換要快

    Qt執行的暫停與重新啟動

    參考:http://www.360doc.com/content/15/0713/11/20016257_484603805.shtml 在Qt中實現繼承QThread的新執行緒的暫停與重新啟動的方法,主要採用互斥量的方法,新執行緒一般都採用while迴圈,來實現程式的不斷

    Qt執行同步(生產者消費者模式

     簡述 生產者將資料寫入緩衝區,直到它到達緩衝區的末尾,此時,它將從開始位置重新啟動,覆蓋現有資料。消費者執行緒讀取資料並將其寫入標準錯誤。 Semaphore(訊號量) 比 mutex(互斥量)有一個更高階的併發性。如果緩衝區的訪問由一個 QMutex 把守,當生產者

    qt GUI執行其他執行的訊號槽以及不同執行通訊

    Qt所有的對於GUI的操作只能在一個GUI執行緒中執行,也就是return QApp::exec的執行緒。 一般main裡面這樣寫。那麼所有的GUI的操作只能在main主執行緒中執行。 int main(int argc, char *argv[]) {QApplicat

    Qt執行執行的等待喚醒】QWaitCondition

    QWatiCondition的成員函式 ·QWaitCondition() ·~QWaitCondition() ·bool wait ( QMutex * mutex, unsigned long time = ULONG_MAX ) ·vo

    Java併發程式設計執行生命週期、守護執行、優先順序join、sleep、yield

    Java併發程式設計中,其中一個難點是對執行緒生命週期的理解,和多種執行緒控制方法、執行緒溝通方法的靈活運用。這些方法和概念之間彼此聯絡緊密,共同構成了Java併發程式設計基石之一。 Java執行緒的生命週期 Java執行緒類定義了New、Runnable、Running Man、Blocked和Dead

    qt執行 std::thread

    不時見到有人會這樣做: 不使用QThread,而是使用pthread等平臺相關的底層 api 而又不想使用底層執行緒間同步、通訊的api 那麼,如何使用pthread,而又使用Qt提供的執行緒間機制呢? 本文的初衷源於此,但是使用的的是C++0x 的 std::threa

    Qt中通過訊號槽在子執行執行中進行資料傳遞

    QT中兩個執行緒之間進行自定義型別資料傳遞 兩個執行緒中進行資料傳遞時,傳遞的資料放到佇列中(queue),所以在這個過程中,需要在傳遞前將資料拷貝、儲存到佇列中;為了儲存這些引數,Qt需要construct、destruct、copy這些物件,為了讓Qt知道

    java執行建立的兩種方式,六種狀態匿名內部類建立子類或實現類物件

    一.匿名內部類建立子類或實現類物件 new Test(){} 相當於建立了Test類的子類物件 並且沒有類名 建立介面實現類 new 介面名() {};介面實現類的物件 注意 : new 後邊是類或者介面名 大括號內是類或者介面中的方法 public

    併發伺服器三種實現方式程序、執行select

      前言:剛開始學網路程式設計,都會先寫一個客戶端和服務端,不知道你們有沒有試一下:再開啟一下客戶端,是連不上服務端的。還有一個問題不知道你們發現沒:有時啟伺服器,會提示“Address already in use”,過一會就好了,想過為啥麼?在這篇部落格會解釋這個問題。   但現實的伺服器都會連很多客戶

    《Android開發藝術探索》學習筆記Android的執行執行

    一、概述 1、主執行緒與子執行緒 主執行緒 又叫UI執行緒 主要作用是執行四大元件以及處理它們和使用者的互動,主要用來處理和介面相關的事情 子執行緒 執行耗時任務,比如網路請求、I/O操作等

    JAVA語言規範-執行鎖章節同步、等待通知

    原文連結  本文是Oracle官方《Java語言規範》的譯文 JAVA語言規範:執行緒和鎖 1 同步 JAVA程式語言提供了執行緒間通訊的多種機制。這些方法中最基本的是同步化,此方法是使用監視器實現的。JAVA中每個物件與一個監視器相關聯,一個執行緒可以加鎖和解鎖監視器。一次僅有一個執行緒可能

    Linux--多執行執行的建立退出

    #include "apue.h" /** 1.main函式的執行緒稱為初始執行緒或主執行緒,主執行緒在main函式返回的時候,會導致 整個程序結束。可以在主執行緒中使用pthread_exit函式 退出主執行緒 如此, 程序會等待所有的執行緒結束時候才終止 */ stru

    Qt執行 - 繼承QObject方式

    Qt執行緒 - 繼承QObject方式 Qt使用執行緒有兩種方式,在新版本的Qt中,Qt官方推薦使用繼承QObject的方式,本文件記錄使用此方法執行緒的實驗過程。 本文轉自:http://beself.top/2018/11/09/qt-thread-inhe

    《完美Qt執行呼叫定時器

    線上程中呼叫定時器 嗨,大家好,我們都知道無論執行緒和定時器,這兩個單獨使用都非常簡單,Qt幫助文件有很詳細的Demo。但是線上程中使用定時器就稍微有點麻煩了,一不注意就容易掉坑裡。 首先理解connect的第五個引數很重要—連線型別 1、connec

    java虛擬機器學習執行共享記憶體區執行私有區

     執行緒共享指的就是可以允許被所有執行緒共享訪問的一塊記憶體,包括堆區,方法區和執行時常量池。  1. java堆區      java堆區在虛擬機器啟動時被建立,並且他在實際記憶體中是可以不連續的。

    【玩轉cocos2d-x二十二】多執行同步02-售票

    pthread有很多不同應用,官網都有相應的API解釋和Sample,這裡不再重複,本文主要介紹一個cocos2d-x多執行緒和同步示例。 1.售票 孫鑫老師的C++和Java多執行緒售票一直讓

    【玩轉cocos2d-x二十三】多執行同步03-圖片非同步載入

    cocos2d-x中和Android,Windows都一樣,如果在主執行緒中處理一些耗時操作,那麼主執行緒就會出現阻塞現象,表現在介面上就是卡住,未響應等情況。為了避免這種情況的出現,我們需要在後