2016-01-02 58 views
0

我有一個單一類實現使用Q_GLOBAL_STATIC包含一個數據結構,必須從多個線程訪問,我在類中實現訪問器函數,這將訪問數據,以便所有對共享數據的訪問都被序列化。使用QAbstractTableModel中的多個線程之間共享的數據

的問題是,我想在一個QAbstractTableModel使用這些數據,我可以簡單地從我重寫data()columnCount()rowCount()使用存取功能,我實現並獲得一個項目在一個時間。但我認爲這是不夠的,因爲在後續的兩個調用data()之間,另一個線程可能會跳入並更改項目數(例如rowCount()),並且模型的線程可能最終訪問超出界限的數據。

我想我需要的columnCount()和模型復位rowCount()最先調用之前鎖定的互斥體,和解鎖,只有當所有的數據讀入模型(以data()最後一次通話後),有沒有這樣做的方式?還是我在想錯誤的方式?

我想拷貝共享數據結構到模型重置的本地一個(並且只有在複製操作時才鎖定互斥鎖),並且在那之後安全地訪問複製的數據,但這不是過度殺傷?沒有更有效的解決方案嗎?

回答

1

在Qt的Model-View框架中,QAbstractItemModel和QAbstractItemView之間的接口根本不是線程安全的,它被設計爲只與一個線程一起使用,它必須是GUI線程,也就是說, GUI不能在主(GUI)線程以外的其他線程中安全地完成。

因此,模型必須保存自己的數據並將其與實際數據同步。如果數據集很大,則可以依靠fetchMore()來避免複製每個模型實例中的全部數據。看看在QtSql's sql models code中做了什麼。然後,您提出的鎖定電話問題更容易解決。

如果真正的數據持有者對象能夠發出連接到模型實例的信號,您甚至可以以事件驅動的方式更新模型。由於自動/排隊信號連接,模型插槽將在主(GUI)線程中執行,因此不需要與QAbstractItemModel-QAbstractItemView接口進行線程安全。

+0

PS:您仍然可以在幾個模型實例之間共享數據,因爲所有視圖都由主(GUI)線程執行,並且不會同時調用兩個模型。 – Jim

+0

感謝您的回答,我想我將不得不切換到單線程設計,以避免這樣的問題 – Mike