老Qt都不一定清楚的“線程親和性”
與題目無關
??感覺自己還挺2,有粉絲點了那個契約者會給up發個鼓勵的話,我還以為是人私信發的,都挨個感謝了,后來才意識到是系統自動發的😣😣😣。
??自上上期視頻對Qt
的槽函數執行在哪個線程做了分享之后,針對評論進行擴展學習,越發覺得自己對Qt
底層不甚了解。盡管自己是從MFC
轉的Qt
,對windows
的消息有一定的技術儲備,但是Qt
做了封裝之后,真就很多東西你要是光用的話很簡單,但是深入下去搞懂Qt
的源碼,那就任重道遠了。
??各平臺對Qt
信號槽的機制講解結合我最近對源碼的閱讀,屬實是粗淺。后期想針對Qt
的信號槽這塊的源碼,從moc.exe
編譯出的cpp
文件逐行代碼講起,將Qt
信號槽講透徹,其中必然涉及:d指針、事件循環、事件內核對象、窗口消息機制、以及很多幫助文檔查不到的源碼中存在的類。這就得整成成套的教程了,規劃9月30號前把這塊弄好。
簡介
??本文繼續圍繞QThread
和QTimer
那個例子進行講解。分析Qt
槽函數執行在哪個線程,只不過這次拿官方的幫助文檔背書。從手冊中找解答。
一、回顧信號槽連接的connect函數
Qt
信號槽連接的幾種方式
??這是一個枚舉值,描述了信號與槽的連接類型,連接類型會決定槽是被立即執行還是稍后執行。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vXLhL8l8-1691917098505)(F:\B站視頻\Qt教程\Qt連接的幾種方式.png)]
??自動連接:接收者與發送者在同一個線程構建,信號槽就會是直接連接,否則就是入隊連接。連接類型具體是什么是當信號發出的時候才決定。
??直接連接:當信號發出的時候,槽被立即調用,槽執行在發信號的線程。
??入隊連接:槽執行在接收者的線程。當控制返回接收者線程的事件循環時槽被調用。
??阻塞入隊連接:與入隊連接一樣,除了發信號的線程會被阻塞直到槽返回阻塞才會失效。如果發信號和槽是在同一個線程使用這種連接會造成死鎖。
??獨占連接:一個信號只能連接到一個槽。可以與上面的四種組合使用。
二、本文的主角-“線程親和性”
知識點:
- 一個
QObject
是存活在一個確定的線程的,這就叫線程的親和性。 - 一個
QObject
接收到一個入隊的信號或post出的事件,槽或者事件處理器會運行在QObject
存活的那個線程。
如果一個對象沒有線程親和性,或所在的線程沒有事件循環,則這個對象不會接收到信號和事件。
- 默認情況下,
QObject
執行在創建它的那個線程,可以通過thread()
查詢它的線程親和性。 - 線程親和性可以被
moveToThread()
改變。 - 所有的
QObject
與他們的父是同一個線程。
如果兩個對象處于不同的線程,
setParent()
會失敗
moveToThread()
會失敗,如果QObject
已經有父了。如果
QObject
在run函數中創建,它們就不能變成QThread
對象的孩子,因為QThread
不存活在調用QThread::run
的線程。
- 一個
QObject
的成員變量不會自動變成該類的子對象的,除非是構造函數傳參,或者是調setParent
。不指定父子關系,類的成員變量任然生存于老線程。
三、其實也不要以為Qt
多牛逼,老馬說過:“任何觀念都可以從現實世界中找到其物質的“原型”
??線程親和性這個技術也是有跡可循,參考下面的文章。
linux進程、線程與cpu的親和性(affinity) - zhangwju - 博客園 (cnblogs.com)