<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Qt雜談6.淺談Qt信號槽那些事

      1 引言

      Qt信號槽是一大特色,介紹它的文章也數不勝數,為啥還要說呢,主要還是想從實現原理作為切入點,談談一個信號發射到槽函數執行所經歷的大致流程,從宏觀角度進行一個簡單梳理,相比于一般的文章稍微深入一點點吧,畢竟水平有限,希望能幫到一些有一定Qt基礎的人。

      2 信號槽執行流程

      這里主要分析信號槽隊列連接方式,比較有代表性一點。

      2.1 建立連接

      首先,使用QObject::connect()函數建立信號與槽的連接,這些信號槽的連接信息將以 QObjectPrivate::Connection 對象的形式存儲在 ConnectionList(QList<QObjectPrivate::Connection>) 列表中。每一個 Connection 對象包含了信號發送者對象的指針、信號的索引(對應于發送者信號列表中的位置)、槽的接收者對象的指針、槽的方法信息、連接的類型、額外的連接標志或者參數。

      連接的類型一般有三種:
      直接連接(DirectConnection):槽函數會直接在信號發射的那個線程上立即執行。
      隊列連接(QueuedConnection):如果信號和槽屬于不同的線程,槽函數的執行將會在目標槽所屬對象的事件循環中異步執行。為了達到這個目的,Qt 會封裝一個 QMetaCallEvent 事件。
      阻塞隊列連接(BlockingQueuedConnection):與隊列連接類似,但是發射信號的線程會阻塞等待槽函數執行完畢。

      其中,ConnectionList 是一個鏈表數據結構,它保存了與一個特定信號相關聯的所有連接,在內存中動態分配,通常在對象被創建時初始化。如何關聯上呢?QObject 類有一個指向 QObjectPrivate 類型的私有數據指針(d_ptr),QObjectPrivate 包含一個或多個 ConnectionList 實例,需要注意的是每一個信號對應一個 ConnectionList。

      2.2 發射信號

      當信號被發射時,moc生成的QMetaObject::activate函數會被調用,它會負責查找所有與信號鏈接的槽,并依次調用每個槽。

      1. 首先通過 QObjectPrivate 獲取到所有的信號槽連接信息;
      2. 通過發射信號的索引,activate() 函數可以確定哪些 Connection 對象是與當前發射的信號相關的;
      3. activate() 函數遍歷與信號相關的所有 Connection 對象。對于每個 Connection,它會根據連接時的類型來決定是直接調用槽函數,還是將調用事件(QMetaCallEvent)推送到指定接收者的事件隊列中;
      4. 如果槽是在相同線程被直接連接的,那么 QObject::activate() 會直接調用該槽函數。如果是跨線程連接的方式,事件將被排隊,在接收者對象所處線程的事件循環中被處理,隨后調用對應的槽函數;
      5. 對于每個槽函數的調用,activate() 會傳遞正確的參數,這是通過從信號發射時傳遞的參數列表中復制參數實現的。

      2.3 執行槽函數

      前面提到,在信號發射時,Qt會檢查這些連接并確定如何調用關聯的槽函數。如果連接是 Qt::DirectConnection 并且信號與槽位于同一線程,那么槽會直接被調用,如果連接是 Qt::QueuedConnection 或者信號與槽位于不同的線程,Qt 則會創建一個 QMetaCallEvent。

      1. 封裝事件(Event Wrapping):
        如果連接類型是 Qt::QueuedConnection 或 Qt::BlockingQueuedConnection,并且發射信號的線程與接收槽的線程不同,Qt會創建一個特殊的事件對象 QMetaCallEvent,它包含了調用槽函數所需的所有信息,包括接收者的槽函數指針、參數值的拷貝等。
      2. 事件投遞(Event Posting):
        生成的事件被投遞到接收對象所屬線程的事件隊列中。Qt使用QCoreApplication::postEvent()函數在應用程序的主事件循環中投遞事件,在這個過程中,發射信號的線程不會阻塞等待(除非是 Qt::BlockingQueuedConnection 類型,這時會等待槽方法執行完畢)。
      3. 事件處理(Event Processing):
        在接收者所屬線程,線程的事件循環將持續運行等待事件,接收者線程的事件循環收到 QMetaCallEvent 后,會根據事件中封裝的信息,調用目標對象的 qt_metacall 函數執行相應的槽方法。
        qt_metacall 是 Qt 框架中的一個特殊成員函數,它是 QObject 類的一部分,它允許動態調用槽和操作屬性,由 Q_OBJECT 宏定義,是元對象系統的核心,它允許實現反射和對象間的通信,而 QMetaCallEvent 是一種用于線程間槽調用的事件。這兩者協同工作,使得 Qt 的信號和槽機制可以跨線程安全地操作。
      4. 槽函數執行(Slot Invocation):
        在 qt_metacall 函數中,根據事件的信息,使用反射機制調用具體的槽函數,并將參數傳遞給它。這樣,即便是跨線程,槽函數也可以在接收者所在線程的上下文中被正確執行。

      3 總結

      很多東西被隱藏在Qt的元對象系統內部,通常開發者不必直接訪問或操作這些內部數據結構,但是如果想理解得更加深入,還是需要對實現原理做一定的了解。好了,有不對的地方,還請大家不吝賜教。

      posted @ 2023-12-19 17:22  Qt小羅  閱讀(412)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 97超级碰碰碰久久久久| 午夜福利影院不卡影院| 亚洲精品无码久久千人斩| 亚洲综合无码日韩国产加勒比| 国产成人午夜福利院| 亚洲全网成人资源在线观看| 日韩丝袜亚洲国产欧美一区| 91老熟女老人国产老太| 尹人香蕉久久99天天拍欧美p7 | 成人又黄又爽又色的视频| 国语对白做受xxxxx在线中国| 亚洲一二三四区中文字幕| 国产明星精品无码AV换脸| 永久无码天堂网小说区| 国产精品青草久久久久福利99| 国产日韩一区二区天美麻豆| 亚洲精品国产福利一区二区 | 四虎国产精品永久在线看| a级国产乱理伦片在线观看al| 欧美国产日韩久久mv| 亚洲精品国产综合麻豆久久99| 亚洲人午夜精品射精日韩| 日本一区三区高清视频| 国产av一区二区亚洲精品 | 中文字幕精品亚洲无线码二区| 周口市| 国产一级精品在线免费看| 宅男噜噜噜66在线观看| 欧美三级在线播放| 国产成人高清亚洲综合| 中文字幕日韩国产精品| 国内精品伊人久久久久777| 久久久久久国产精品美女| 午夜福利片1000无码免费| 汪清县| 视频一区视频二区视频三| 国产揄拍国产精品| 久久综合亚洲色一区二区三区| 国产极品粉嫩学生一线天| 欧美孕妇乳喷奶水在线观看| 中文字幕国产日韩精品|