Qt 多線程中的信號/槽

Qt 多線程中的信號/槽

 

connect函數的五個參數表示的意義依次爲:sender*, signal, receiver*, slot,connectionTpye

其中槽可以是receiver的成員函數,或者是任意可訪問的靜態函數。在多線程的情形下:

 

1. 一個對象的線程就是創建該對象時的線程,而不論該對象的定義是保存在那個線程中;

  比如在thread1中開了個新線程thread2,那麼thread2 對象就是定義在thread1中的,即thread2對象本身是屬於thread1的,而在thread2的run函數中定義的對象則是屬於thread2的。

2. QObject的connect函數有幾種連接方式,

      a) DirectConnection,信號發送後槽函數立即執行,由sender的所在線程執行;

      b) QueuedConnection,信號發送後返回,相關槽函數由receiver所在的線程在返回到事件循環後執行;

      c) 默認使用的是Qt::AutoConnection,當sender和receiver在同一個線程內時,採用DirectConnection的方式,當sender和receiver在不同的線程時,採用QueuedConnection的方式。

 

所以如果發生了跨線程調用,即在線程a中使用了線程b的對象就會報各種錯誤,如:

Cannot create children for a parent that is in a different thread

QSocketNotifier: socket notifiers cannot be enabled from another thread

Assert failure:Cannot send events toobjects owned by a different thread

 

產生這個問題的原因就是因爲sender跟receiver可能是屬於不同的線程,可能會導致發出信號的線程與接收信號執行槽函數的線程不同。比如sender發出信號x,讓槽函數處理一下某些數據,這些數據顯然跟sender是在一個線程的,但執行槽函數的時候線程切換了,就等於在處理別的線程的數據了。

解決辦法有:

1,採用直接連接方式,讓槽函數在發出信號的對象所依賴的線程中執行,也就是不讓信號進入消息隊列,直接處理,但是這樣貌似需要對線程同步進行處理。

2,將receiver移動至sender的線程,比如在thread1中創建了一個thread2,在thread2的run函數中創建了一個obj。想讓obj發出信號,然後thread2對象來處理,那麼在創建thread2之後把thread2用moveToThread(thread2)移動到thread2中即可,這樣sender跟receiver就在同一個線程中了,不過拘束不推薦這麼做

3,文檔中推薦的方法爲:在run函數中創建一個對象,這個對象肯定是屬於thread2的,然後使用thread2作爲revcever來處理信號即可

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