1. 程式人生 > >Qt中連線到同一signal的多個slots的執行順序問題

Qt中連線到同一signal的多個slots的執行順序問題

  • in the order they have been connected

起源

前些天忘記在哪兒討論過這個問題,今天在csdn又看到有網友問這個問題,而其他網友卻無一例外的給出了“無序”這個答案。

Manual

Qt的問題,當manual中有明確文字說明時,我們應該以Qt的manual為準:

If several slots are connected to one signal, the slots will be executed one after the other, in the order they have been connected, when the signal is emitted.
If a signal is connected to several slots, the slots are activated in the same order as the order the connection was made, when the signal is emitted.

恩,說的很明確,各個槽按照被connect的順序被執行【注意,在佇列模式時,是指相應的事件被post,仍不保證槽被按照該順序執行】。

可是,為什麼很多人認為是無序呢?(除了前面提及的,還有什麼其他因素麼?)

翻翻Qt4.5以及該版本之前的manual,可以看到

If several slots are connected to one signal, the slots will be executed one after the other, in an arbitrary order, when the signal is emitted.
If a signal is connected to several slots, the slots are activated in an arbitrary order when the signal is emitted.

網路上以及書籍中的大部分資料都是Qt4.6之前的,故爾 ...

原始碼

恩,嘗試看過元物件系統這部分原始碼的網友對這部分不會覺得陌生。如果沒看過,可以瞅瞅這個Qt Meta Object system 學習(三)

  • QObject::connect() 最終將 訊號和槽的索引值放置到一個Connection列表中
QObjectPrivate::Connection *c = new QObjectPrivate::Connection; 
    c->sender = s; 
    c->receiver = r; 
    c->method = method_index; 
    c->connectionType = type; 
    c->argumentTypes = types; 
    c->nextConnectionList = 0; 
QObjectPrivate::get(s)->addConnection(signal_index, c); 
  • 訊號的發射,就是藉助QMetaObject::activate() 來依次處理前面那個Connection列表總的項

do { 
        QObjectPrivate::Connection *c = connectionLists->at(signal_index).first; 
        if (!c) continue; 
        // We need to check against last here to ensure that signals added  
        // during the signal emission are not emitted in this emission. 
        QObjectPrivate::Connection *last = connectionLists->at(signal_index).last;
 
       do { 
            if (!c->receiver) 
                continue; 
             QObject * const receiver = c->receiver;

在該過程中:

  • 如果是直接連線,則通過 QMetaObject::metacall() 直接呼叫
  • 如果是佇列連線,則post一個QMetaCallEvent事件,稍後通過事件派發,該事件的處理函式負責通過 QMetaObject::metacall() 呼叫相應的槽函式【注意,小心此時槽函式的執行順序】

注意:此處的程式碼片段是Qt4的,而Qt5.0 中由於引入了新式的訊號和槽語法,對應部分原始碼有較大變化。

參考


相關推薦

AsyncTask執行順序:並行or序列

AsyncTask作為一個優秀的封裝,很多人都在用,可是我估計很多人並不清楚多個AsyncTask物件到底是序列執行的,還是並行執行的,如果是並行的,那麼最多同時執行幾個非同步任務呢? 原始碼面前無祕密,我們看一下原始碼就知道了。 這裡以Android-23為例。 Ayn

Qt連線同一signalslots執行順序問題

in the order they have been connected 起源 前些天忘記在哪兒討論過這個問題,今天在csdn又看到有網友問這個問題,而其他網友卻無一例外的給出了“無序”這個答案。 Manual Qt的問題,當manual中有明確文字說明時,

QT專案新增並使用UI佈局介面

在工程的“介面檔案”資料夾上右鍵選擇“新增新檔案”; 選擇“Qt -> Qt Designer Form”新增新的佈局檔案; 新建兩個.ui檔案 dialog1.ui,dialog2.ui 記住要修改一下objectName的內容,不然所有的obje

spring boot使用spring JdbcTemplate(一)——連線池建立連線

本文參考了網上一些文章,最後整理實踐得出。1、建立一個springboot的demo程式,可以參考我的文章:2、看一下目錄結構:3、首先需要在pom檔案中引入依賴:<!-- https://mvnrepository.com/artifact/mysql/mysql-c

Python 字典一鍵對應

列表 檢查 span mark blog class efault remove one #字典的一鍵多值 print‘方案一 list作為dict的值 值允許重復‘ d1={} key=1 value=2 d1.setdefault(key

asp.net core1.x/asp.net core2.0如何加載配置文件

加載 自己 團隊 多配置文件 做的 ted 文章 pos 簡單 寫這篇文章,來簡單的談一下,asp.net core中,如何加載多配置文件,如有錯誤請斧正。 在1.x的時候,我們是自己配置 WebHostBuilder而在2.0的時候,ef core團隊,將配置寫到了

Selenium怎麽實現窗口之間的切換?

Selenium切換窗口 Selenium利用句柄切換窗口 Selenium窗口之間的切換 Selenium怎麽操作其他的窗口 Selenium 多窗口(多Tab)之前的切換 多窗口的切換的目的是為了讓selenium改變操作的窗口。在selenium中假如不切換窗口,一旦遇到一個鏈接跳轉到另

VS2013無法載入解決方案專案,提示未能正確載入解決方案的一個或專案

現象:開啟一個工程,上午還能正常操作,下午就打不開了。試了所有的工程都打不開。 提示: 未能正確載入解決方案中的一個或多個專案 解決辦法: 1、關閉VS; 2、去C:\Users\AppData\Local\Microsoft\VisualStudio\12.0\ComponentMod

Python字典的鍵對映值(列表或者集合)

一個字典就是一個鍵對應一個單值的對映。如果你想要一個鍵對映多個值,那麼你就需要將這多個值放到另外的容器中, 比如列表或者集合裡面。比如,你可以像下面這樣構造這樣的字典: d = { 'a' : [1, 2, 3], 'b' : [4, 5] } e = { 'a'

ztree外掛同一頁面tree想要每個tree有獨立的點選事件

在同一個頁面如果有兩個tree,而且想要兩個tree的點選事件區別開來,需要設定獨立的一套setting和回撥函式,如下: //第一棵樹 var setting = { isSimpleData : true, //資料是否採用簡單 Ar

使用strings.xml文字資源發現空格只顯示一個空格

先上圖 strings.xml程式碼如下: <resources> <string name="app_name">Test</string> <string name="app_text">型別:型別1\n

java 從字串 以單個或空格進行分隔 提取字串

    String str = "test test1 test2 test3"; String [] arr = str.split("\\s+"); for(String ss : arr){

web.xml一個filter配置url-pattern

需要在filter標籤後新增多個filter-mapping標籤,一個url-pattern就對應一個filter-mapping標籤,不能直接把多個url-pattern配置到同一個filter-mapping標籤裡,也不能直接把多個url直接配置到一個url-pattern標籤裡。 正確地配置方式如下所

bootstrap利用Tag實現div的上下頁切換

func acc tex oot trap www. active cli ane 添加 nav 和 nav-tabs 類到 ul 中,將會應用 Bootstrap 標簽樣式,添加 nav 和 nav-pills 類到 ul 中,將會應用 Bootstrap 膠囊式樣式 &

一個Action,可以寫類似的業務控制方法

1)通過模組根路徑 + 功能子路徑 = 訪問模組下子功能的路徑 @Controller @RequestMapping(value="/user") public class UserAction{ @RequestMapping(value="/add") public St

因解決narinder-agent啟動報錯問題---MAC使用JENV管理java版本

背景 在使用ngrinder+tomact+jdk時,這裡遇到一個坑,我自己的MAC電腦java安裝的最新版本,jdk是10.0.1版本,在後面啟動ngrinder相關的java專案時,會報錯,啟不來,因為版本過高,有的類找不到,需要在jdk1.8下啟動。又安裝了一個j

列表的使用(append,count,extend,index,pop,remove)dir;找出列表指定一個或元素並刪除

斜體樣式列表:在一個數組裡存或者取多個資訊 列表操作功能有:索引 切片 追加 刪除 長度 迴圈 包含 列表舉例:name_list=[“R”,“u”,“b”,“y”] print(name_list[1]) >>>u pr

同一頁面ajax請求後臺堵塞問題

有個小夥子告訴我,一個頁面上同時開啟多個ajax,向後臺請求資料,會被堵塞。 “因為是同一個會話。但如果在控制器上加上這個特性就可以了”,小夥子說。 //session只讀,避免同一會話中ses

在Linux替換目錄下檔案的字串

在Linux中,替換多個檔案中的某個字串可以使用grep和sed的組合來實現這個功能。 基本格式 grep -rl matchstring somedir/ | xargs sed -i 's/string1/string2/g' matchstring是你將要被替換

關於html,巢狀盒子浮動的問題。

//貼上程式碼 <!DOCTYPE html> <html>     <head>         <meta charset="utf-8" />         <title></title>