简体   繁体   English

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

[英]using data shared between multiple threads in a QAbstractTableModel

I have a singleton class implemented using Q_GLOBAL_STATIC that contains a data structure that has to be accessed from multiple threads, I implemented accessor functions in the class, that would lock a mutex before accessing the data, so that all accesses to the shared data are serialized. 我有一个使用Q_GLOBAL_STATIC实现的单例类,该类包含必须从多个线程访问的数据结构,我在该类中实现了访问器函数,该函数将在访问数据之前锁定互斥体,以便对共享数据的所有访问都被序列化。

The problem is that I want to use this data in a QAbstractTableModel , I can simply use the accessor functions I implemented and access one item at a time from my overridden data() , columnCount() and rowCount() . 问题是我想在QAbstractTableModel使用此数据,我可以简单地使用实现的访问器函数,并一次从覆盖的data()columnCount()rowCount()访问一项。 But I think this is insufficient, since between two subsequent calls to data() another thread may jump in and change the number of items for example ( rowCount() ), and the model's thread may end up accessing out of bounds data. 但是我认为这是不够的,因为在两次随后的对data()调用之间,另一个线程可能会跳入并更改项数(例如rowCount() ),并且该模型的线程可能最终会访问超出范围的数据。

I think I need to lock the mutex before the very first call of columnCount() and rowCount() of the model reset, and unlock it only when all data is read into the model (after the last call to data() ), is there a way to do so? 我认为我需要在首次重置模型的columnCount()rowCount()之前锁定互斥锁,并且仅在将所有数据读入模型(最后一次调用data() )时才将其解锁有办法吗? or am I thinking the wrong way? 还是我想错了方向?

I thought of copying the shared data structure to a local one on model reset(and have the mutex locked only on the copy operation), and after that access the copied data safely, but isn't that an overkill? 我想到了在模型重置时将共享数据结构复制到本地结构(并且仅在复制操作上锁定了互斥锁),然后安全地访问复制的数据,但这不是一个过大的功能吗? isn't there a more efficient solution? 没有更有效的解决方案吗?

In Qt's Model-View framework, the interface between QAbstractItemModel and QAbstractItemView is not threadsafe at all, it is designed to be used with only one thread, which must be the GUI thread, ie the main thread since view does painting on the GUI, which cannot be done securely in another thread than the main (GUI) thread. 在Qt的Model-View框架中,QAbstractItemModel和QAbstractItemView之间的接口根本不是线程安全的,它被设计为仅与一个线程一起使用,该线程必须是GUI线程,即主线程,因为视图确实是在GUI上绘制的,因此无法在除主(GUI)线程之外的其他线程中安全地完成操作。

Therefore a model must hold it's own data and synchronize it with real data. 因此,模型必须拥有自己的数据,并将其与真实数据同步。 If your dataset is large, you can rely on fetchMore() to avoid copying the whole data in every model instance. 如果数据集很大,则可以依靠fetchMore()避免在每个模型实例中复制整个数据。 See what is done in QtSql's sql models code . 查看QtSql的sql模型代码中完成的操作 Then the lock-between-calls issue you raise is easier to solve. 这样一来,您提出的通话间锁定问题就更容易解决。

You can even update the model in an event-driven way if the real data holder objects are able to emit signals connected to the model instance. 如果实际数据持有者对象能够发出连接到模型实例的信号,您甚至可以事件驱动的方式更新模型。 Thanks to auto/queued signal connections, the model slots will execute in the main (GUI) thread and therefore won't need to be threadsafe with the QAbstractItemModel-QAbstractItemView interface. 由于自动/排队信号连接,模型插槽将在主(GUI)线程中执行,因此不需要使用QAbstractItemModel-QAbstractItemView接口实现线程安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM