使用QAbstractTableModel中多个线程之间共享的数据

时间:2016-01-02 05:17:32

标签: c++ multithreading qt qabstracttablemodel qmutex

我有一个使用Q_GLOBAL_STATIC实现的单例类,它包含一个必须从多个线程访问的数据结构,我在类中实现了访问器函数,它会在访问数据之前锁定互斥锁,这样所有对序列化的共享数据的访问。

问题是我想在QAbstractTableModel中使用这些数据,我可以简单地使用我实现的访问器功能,并从被覆盖的data(),{{1}一次访问一个项目}和columnCount()。但我认为这是不够的,因为在两个后续调用rowCount()之间另一个线程可能会跳入并更改项目数量(例如data()),并且模型的线程可能会结束访问越界数据。

我想我需要在第一次调用模型重置的rowCount()columnCount()之前锁定互斥锁,并且只有在所有数据都被读入模型时才会解锁(在最后一次调用之后)到rowCount()),有没有办法这样做?或者我的想法是错误的?

我想过在模型重置时将共享数据结构复制到本地数据结构(并且仅在复制操作上锁定互斥锁),之后安全地访问复制的数据,但是不是一种过度杀伤力?是不是有更有效的解决方案?

1 个答案:

答案 0 :(得分:1)

在Qt的Model-View框架中,QAbstractItemModel和QAbstractItemView之间的接口根本不是线程安全的,它被设计为只与一个线程一起使用,该线程必须是GUI线程,即主线程,因为视图在GUI,不能在主(GUI)线程之外的另一个线程中安全地完成。

因此,模型必须保存自己的数据并将其与实际数据同步。如果数据集很大,则可以依赖fetchMore()来避免在每个模型实例中复制整个数据。看看QtSql's sql models code中做了什么。然后你提出的锁定之间的问题更容易解决。

如果真实数据持有者对象能够发出连接到模型实例的信号,您甚至可以以事件驱动的方式更新模型。由于自动/排队信号连接,模型插槽将在主(GUI)线程中执行,因此不需要使用QAbstractItemModel-QAbstractItemView接口进行线程安全。