1. 程式人生 > >Qt中QEvent和訊號槽的區別

Qt中QEvent和訊號槽的區別

4.

Qt::AutoConnection
If the signal is emitted from the thread in which the receiving object lives, the slot is invoked directly, as with Qt::DirectConnection; otherwise the signal is queued, as with Qt::QueuedConnection.
這種連線型別根據signal和slot是否在同一個執行緒裡自動選擇Qt::DirectConnection或Qt::QueuedConnection

這樣看來,第一種型別的效率肯定比第二種高,畢竟第二種方式需要將訊息儲存到佇列,而且可能會涉及到大物件的複製(考慮sig_produced(BigObject bo),bo需要複製到佇列裡)。

Qt的執行緒和 signal-slot

再問coredump或者QT高手們一個問題。QT裡用執行緒,主執行緒是GUI,次執行緒是工作執行緒,如果次執行緒裡也用訊息迴圈(exec),即,主/次間用signal-slot通訊來實現同步,在這種情況下, 1.主執行緒會被次執行緒block嗎? 2.如果在單cpu裡會被block嗎,如果次執行緒裡不斷迴圈,低層會自動分配時間片給主執行緒嗎? 3.這種方法和直接呼叫次執行緒中的方法,用mutex之類的來實現類似的迴圈,效率差別大嗎?記得QT裡講過signal-slot只是多幾個函式呼叫的差別。 呵呵,問的不太清楚,主要就是想問一下,主次執行緒中怎樣通訊比較有效。 謝謝阿。

QThread 現在預設狀態下就是有一個訊息迴圈的,而且鼓勵使用執行緒獨立的訊息迴圈 1.主執行緒會被次執行緒block嗎? 不會,QObject::connectd的最後一個引數預設使用Qt::AutoConnection, 在多執行緒環境下,會自動選擇Qt::QueuedConnection方式,除非強制使用Qt::BlockingQueuedConnection或者 Qt::DirectConnection, 否則執行緒不會block. 2.如果在單cpu裡會被block嗎,如果次執行緒裡不斷迴圈,低層會自動分配時間片給主執行緒嗎? 執行緒和CPU個數沒有關係,當然CPU多了,執行會更加流程,執行緒的資源分配(時間片)是由作業系統管理的,在各個系統上都是如此 3.這種方法和直接呼叫次執行緒中的方法,用mutex之類的來實現類似的迴圈,效率差別大嗎? 執行效率上很難講,但是mutex肯定是帶來了開發效率的降低,你得小心翼翼地處理好各種臨界資源的鎖問題 4. 記得QT裡講過signal-slot只是多幾個函式呼叫的差別 是的,signal-slot的這種輕微的效率損失在絕大多數情況下不是問題,除非過度使用,這一般是設計上的錯誤導致的 分享兩篇文章,講QThread和Qt的signal-slot的: 1篇是qt labs的部落格上一篇 You are doing it wrong...(
http://labs.trolltech.com/blogs/2010/06/17/youre-doing-it-wrong/
), 這篇文章很有意思,其實很多人不知道原來QThread還可以這樣用。 另外一篇是關於怎麼利用Qt的signal-slot機制和QThread進行完全的lock free程式設計(http://thesmithfam.org/blog/2009 ... ti-threading-in-qt/)

多謝多謝,再學習去。 之所以問,是因為,我做了一個下載googlemap的程式,開始下載執行緒後,GUI就不動了,直到下載結束。雖然作業系統會分配時間,但是如果下載執行緒迴圈,而且優先順序相同的話,是不是還是有影響?

我再看看哪裡出問題了。 剛看了你上面的兩個連結,真是切中要害阿,呵呵,一直就在琢磨這個一段時間了。 總結一下理解,看看對不對。 第一篇裡,QThread裡預設的run()已經啟動了訊息迴圈exec(). 當需要新執行緒時,應該,直接生成QThread, start()。至於功能,應該放在另外的類裡,在呼叫start前設定好signal-slot,再moveToThread到 QThread中。 不用sunbclass QThread。 我一直或者重新實現run(),在run()裡生成所有object, signal-slot, 或者如文中所說的QThread.moveToThread(QThread). 這兩種都有不少問題,破壞OO的概念。 很清楚。

第二篇裡講了用執行緒間的signal-slot來同步,正好回答了之前的疑問,不過他使用qthread的方法恰恰違背了第一篇的思想。

引用:
原帖由 GPS 於 12-7-2010 12:40 發表  我再看看哪裡出問題了。 剛看了你上面的兩個連結,真是切中要害阿,呵呵,一直就在琢磨這個一段時間了。 總結一下理解,看看對不對。 第一篇裡,QThread裡預設的run()已經啟動了訊息迴圈exec(). 當需要新執行緒時 ...
另一種方式也不錯,有些情況下必須subclass QThread, 錯的不是是否subclass,錯在:subclassing QThread, adding signal and slot code to that subclass, and then calling moveToThread(this);
引用:
To set the record straight: I’m not saying sub-classing QThread is wrong. This is also how Java does it (sort of), and many people have been doing this with Qt for a long time. What I’m saying is “wrong” is subclassing QThread, adding signal and slot code to that subclass, and then calling moveToThread(this); in the constructor of that subclass. This causes people lots of confusion from my experience and observation on the #qt channel and the qt-interest mailing list. And yes, the current docs are still a bit lacking, something that I am fully aware of (and take responsibility for). I’m planning on sitting down and fleshing them out, showing both ways of using QThread (with and without subclassing).
在Qt的程式設計模型裡,thread和signal- slot都是實現非同步程式設計的手段,signal-slot的背後是訊息迴圈,而每個thread都是一個獨立的訊息迴圈,在早期版本,qt執行緒間無法進行 signal-slot訊息傳遞,這就導致了各個訊息迴圈都是互相獨立的loop, 通訊的唯一方式只剩下global state+ mutex lock。在4.x 之後,signal-slot已經能夠和thread融洽相處了。 這樣,理想的QT程式設計模型就變成了獨立的一個個任務,各自 使用自己的thread和thread內部訊息迴圈,在需要互相通訊的時候,使用signal-slot, 這些signal和slot就是明確定義的訊息介面,除此之外,最好不共享其它狀態。Qt程式設計師有點像轉盤子的雜技演員,每個盤子都獨自轉動,整個系統由 很多旋轉的盤子組成,這些盤子可以共享雜技演員一個手,也可以是另一隻手甚至不同的雜技演員來控制(多CPU)//------------------------------------------------------------------------------------------------------------------------
signal由具體物件發出,然後會馬上交給由connect函式連線的slot進行處理;而對於事件,Qt使用一個事件佇列對所有發出的事件進行維護,當新的事件產生時,會被追加到事件佇列的尾部,前一個事件完成後,取出後面的事件進行處理。但是,必要的時候,Qt的事件也是可以不進入事件佇列,而是直接處理的。並且,事件還可以使用“事件過濾器”進行過濾。總的來說,如果我們使用元件,我們關心的是訊號槽;如果我們自定義元件,我們關心的是事件。因為我們可以通過事件來改變元件的預設操作。比如,如果我們要自定義一個QPushButton,那麼我們就需要重寫它的滑鼠點選事件和鍵盤處理事件,並且在恰當的時候發出clicked()訊號。
還記得我們在main函式裡面建立了一個QApplication物件,然後呼叫了它的exec()函式嗎?其實,這個函式就是開始Qt的事件迴圈。在執行exec()函式之後,程式將進入事件迴圈來監聽應用程式的事件。當事件發生時,Qt將建立一個事件物件。Qt的所有事件都繼承於 QEvent類。在事件物件建立完畢後,Qt將這個事件物件傳遞給QObject的event()函式。event()函式並不直接處理事件,而是按照事件物件的型別分派給特定的事件處理函式(event handler)。
在所有元件的父類QWidget中,定義了很多事件處理函式,如keyPressEvent()、
keyReleaseEvent()、mouseDoubleClickEvent()、mouseMoveEvent ()、mousePressEvent()、mouseReleaseEvent()等。這些函式都是protected virtual的,也就是說,我們應該在子類中重定義這些函式。
轉自網路