2011-07-11 16 views
2
WMIQuery::wmiquery(WMI::WMITable* table, const QString& query, WMI::ProgressIndicator* progressIndicator) 

這是函數簽名。我打電話通過QtConcurrent::run傳遞QModelIndex交叉線程排隊連接

QFuture<quint32> future = QtConcurrent::run(WMI::WMIQuery::wmiquery, _table, query); 

該架構非常簡單。 預期的查詢將返回的行數是已知的。 查詢並行運行,並在每條記錄中取一行加到table: WMI::WMITable* WMI::WMITable是一個簡單的QObject表數據結構。 它在行添加時發出rowsAboutToBeInserted(QModelIndex, int, int)rowsInserted(QModelIndex, int, int)

另一方面ProgressIndicator在主線程上實例化並且table傳遞給它的ctor。它從WMI::WMIQuery::wmiquery()ProgressIndicator::setRecordCount(quint64 count)獲得預期的總行數。 它有一個插槽rowAdded(),它通過一些簡單的數學運算髮現100的進展。在它的連接器上它連接

connect(_table, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowAdded())); 

我的想法。作爲WMI::WMIQuery::wmiquery()我運行在不同的線程上(在QThreadPool)此連接是一個交叉線程排隊連接。我對麼 ?

我得到以下運行時錯誤

的QObject ::連接:無法排隊類型 'QModelIndex'
(確保 'QModelIndex' 使用qRegisterMetaType註冊()。)

的參數

我該怎麼辦?作爲我SLOT(rowAdded())不需要的SIGNAL(rowsInserted(QModelIndex,int,int))的3個參數,我應該讓另一個信號像rowInserted()和發射它,每當我發出rowsInserted(QModelIndex,int,int)並使用此SIGNAL作此coinnection

你可能會問,爲什麼我使用的模型一樣喜歡rowsInserted(QModelIndex,int,int)信號在表數據結構中。因爲我也有一個連接到這個表的模型。這也將逐行更新。不過,我認爲在這方面很重要。

回答

2

前跨線程邊界發射信號與一個不平凡的參數類型(如QModelIndex),您必須首先調用此:

qRegisterMetaType<QModelIndex>("QModelIndex"); 

,準備Qt來能夠發射穿過線程邊界的信號。

通常你會後你QApplication爲此在main()或地方,只運行一次,調用emit,但之前已經被實例化。

這只是非常重要的類型所必需的。例如,像這樣的信號將需要向qRegisterMetaType()

signals: 
    void mySignal(int foo, int bar); 

但是這樣的信號確實需要qRegisterMetaType()

signals: 
    void mySignal(QModelIndex); 

對於更多信息,請參閱Qt文檔:http://doc.qt.nokia.com/latest/qmetatype.html#qRegisterMetaType

+0

另一種選擇是從發出的信號中刪除'QModelIndex'和兩個'int',因爲它們在槽rowadeded()中都沒有收到。 – djsmith

+0

雅我已經試過這種方式,正如我在問題中提到的那樣。它的工作。 –

+0

以及'qRegisterMetaType (「QModelIndex」)''中額外的開銷是多少?應該解決這個問題嗎?這是一個真正的方式?或一個壞的哈克? –

1

我知道這已經很晚了,但我想確定有人提到過它:QModelIndex並不意味着排隊,出於同樣的原因,它不打算以其他方式存儲和使用。也就是說,如果在使用QModelIndex之前模型發生更改,則會出現未定義的行爲。如果您需要使用模型索引排隊的事件,則應該使用QPersistentModelIndex。與原始問題沒有多大關係,但可能適用於在此登陸的人。