一、以前就發(fā)現(xiàn)過這個問題: 在Qt項(xiàng)目中,,有時候?yàn)榱俗屪约旱念?,可以重載操作符 '=','<<','>>'. 也有時候需要用一個類進(jìn)行文件的讀寫,,所以很多C++類還是要簡單化的,,不需要繼承QObject,不需要Qt的元對象機(jī)制,。 但是對于這些簡單C++類,,有些時候要是調(diào)用Qt的信號槽當(dāng)做參數(shù)進(jìn)行跨線程發(fā)送,就會出現(xiàn)如下問題: 這種情況一般,,編譯可以通過,,但會出現(xiàn)如下提示。
意思是說,,信號槽隊(duì)列中的數(shù)據(jù)類型必須是系統(tǒng)能識別的元類型,,不然得用qRegisterMetaType()進(jìn)行注冊。
二,、解決方法: 第一種注冊法:qRegisterMetatType<MoSystemLog>("MoSystemLog") 第二種修改Connect,,加一個屬性Qt::directConnection. connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)), this,SLOT(sendRes(QUuid,QByteArray,bool)), Qt::DirectConnection);
三、方法解釋:
1,、第一種解決方法,,即使用排隊(duì)方式的信號-槽機(jī)制,Qt的元對象系統(tǒng)(meta-object system)必須知道信號傳遞的參數(shù)類型,。這樣元系統(tǒng)可以將信號參數(shù)COPY下來,,放在隊(duì)列中等待事件喚醒,供槽函數(shù)調(diào)用,。Just a note here, if you would have to pass custom data types between threads in Qt. As we know, a signal-slot connection is then (by default) of type Qt::QueuedConnection. Because in such a situation Qt needs to store passed parameters for a while, it creates their temporary copies. If it doesn’t recognize the passed data type, throws out an error: 2,、第二種方法,直接調(diào)用對方槽函數(shù),,不需要保存參數(shù),。但是官方認(rèn)為這樣做有風(fēng)險(xiǎn)。
四,、背景知識: 1,、首先要了解enum Qt::ConnectionType
Qt支持6種連接方式,其中3種最主要: Qt::DirectConnection(直連方式) 當(dāng)信號發(fā)出后,,相應(yīng)的槽函數(shù)將立即被調(diào)用,。emit語句后的代碼將在所有槽函數(shù)執(zhí)行完畢后被執(zhí)行。(信號與槽函數(shù)關(guān)系類似于函數(shù)調(diào)用,,同步執(zhí)行) Qt::QueuedConnection(排隊(duì)方式) 當(dāng)信號發(fā)出后,,排隊(duì)到信號隊(duì)列中,,需等到接收對象所屬線程的事件循環(huán)取得控制權(quán)時才取得該信號,調(diào)用相應(yīng)的槽函數(shù),。emit語句后的代碼將在發(fā)出信號后立即被執(zhí)行,,無需等待槽函數(shù)執(zhí)行完畢。(此時信號被塞到信號隊(duì)列里了,,信號與槽函數(shù)關(guān)系類似于消息通信,,異步執(zhí)行) Qt::AutoConnection(自動方式) Qt的默認(rèn)連接方式,如果信號的發(fā)出和接收這個信號的對象同屬一個線程,,那個工作方式與直連方式相同,;否則工作方式與排隊(duì)方式相同。 Qt官方文檔中寫明: With queued connections, the parameters must be of types that are known to Qt's meta-object system, because Qt needs to copy the arguments to store them in an event behind the scenes. If you try to use a queued connection and get the error message QObject::connect: Cannot queue arguments of type 'MyType' callqRegisterMetaType() to register the data type before you establish the connection. 注意上面紫色的內(nèi)容,。
參考文章: 1,、http://blog./2009/2/15/registering-custom-types 2,、http://dev./bbs/redirect.jsp?fid=25127&tid=150302&goto=nextoldset |
|