1、之前就發現過這個問題:html
在Qt項目中,有時候爲了讓本身的類,能夠重載操做符 '=','<<','>>'. 也有時候須要用一個類進行文件的讀寫,因此不少C++類仍是要簡單化的,不須要繼承QObject,不須要Qt的元對象機制。異步
可是對於這些簡單C++類,有些時候要是調用Qt的信號槽當作參數進行跨線程發送,就會出現以下問題:jsp
這種狀況通常,編譯能夠經過,但會出現以下提示。ide
QOBject::connect:Cannot queue arguments of type 'MoSystemLog' ui
(Make sure 'MoSystemLog' is registed using qRegisterMetaType().) this
意思是說,信號槽隊列中的數據類型必須是系統能識別的元類型,否則得用qRegisterMetaType()進行註冊。spa
2、解決方法:.net
第一種註冊法:qRegisterMetatType<MoSystemLog>("MoSystemLog")線程
第二種修改Connect,加一個屬性Qt::directConnection.
connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)),
this,SLOT(sendRes(QUuid,QByteArray,bool)), Qt::DirectConnection);
3、方法解釋:
一、第一種解決方法,即便用排隊方式的信號-槽機制,Qt的元對象系統(meta-object system)必須知道信號傳遞的參數類型。這樣元系統能夠將信號參數COPY下來,放在隊列中等待事件喚醒,供槽函數調用。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:
二、第二種方法,直接調用對方槽函數,不須要保存參數。可是官方認爲這樣作有風險。
4、背景知識:
一、首先要了解enum Qt::ConnectionType
Qt支持6種鏈接方式,其中3種最主要:
Qt::DirectConnection(直連方式)
當信號發出後,相應的槽函數將當即被調用。emit語句後的代碼將在全部槽函數執行完畢後被執行。(信號與槽函數關係相似於函數調用,同步執行)
Qt::QueuedConnection(排隊方式)
當信號發出後,排隊到信號隊列中,需等到接收對象所屬線程的事件循環取得控制權時才取得該信號,調用相應的槽函數。emit語句後的代碼將在發出信號後當即被執行,無需等待槽函數執行完畢。(此時信號被塞到信號隊列裏了,信號與槽函數關係相似於消息通訊,異步執行)
Qt::AutoConnection(自動方式)
Qt的默認鏈接方式,若是信號的發出和接收這個信號的對象同屬一個線程,那個工做方式與直連方式相同;不然工做方式與排隊方式相同。
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.
注意上面紫色的內容。
connect的第五個參數用於指定反應速度:
若將:
connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)),
this,SLOT(sendRes(QUuid,QByteArray,bool)));
改成:
connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)),
this,SLOT(sendRes(QUuid,QByteArray,bool)), Qt::DirectConnection);
可解決因信號沒有及時發送,導致connect的接收方的槽不能做進一步處理,可是有風險
參考文章:
一、http://blog.ayoy.net/2009/2/15/registering-custom-types
二、http://dev.wo.com.cn/bbs/redirect.jsp?fid=25127&tid=150302&goto=nextoldset