近來用Qt編寫一段多線程的TcpSocket通信程序,被其中Qt中報的幾個warning搞暈了,一會兒是說“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,從而導致程序崩潰。
為徹底搞清原因並解決問題,在查閱大量資料和Qt文檔之後,理清了其中的機制,也對多線程編程中的QObject對象創建以及connect執行有更清楚的認識:
1. 一個對象的線程就是創建該對象時的線程,而不論該對象的定義是保存在那個線程中;
2. QObject的connect函數有幾種連接方式,
a) DirectConnection,信號發送後槽函數立即執行,由sender的所在線程執行;
b) QueuedConnection,信號發送後返回,相關槽函數由receiver所在的線程在返回到事件循環後執行;
c) 默認使用的是Qt::AutoConnection,當sender和receiver在同一個線程內時,采用DirectConnection的方式,當sender和receiver在不同的線程時,采用QueuedConnection的方式。
為了更清楚的理解這些問題,在此特編了個小例子說明一下。首先定義一個從QObject繼承的類SomeObject,包含一個信號someSignal和一個成員函數callEmitSignal,此函數用於發送前面的someSignal信號。定義如下:
// define Object class