Qt:如何在模型/视图设置中同步对来自多个线程的数据的访问?

Posted

技术标签:

【中文标题】Qt:如何在模型/视图设置中同步对来自多个线程的数据的访问?【英文标题】:Qt: How to synchronize access to data from multiple threads in model/view setup? 【发布时间】:2011-12-20 00:41:48 【问题描述】:

如何在 Qt 模型/视图设置中同步对从多个线程访问的数据的访问?

我正在使用 QTableViewModel 类。

Model 扩展 QAbstractTableModel 并具有自定义类 Net 的实例,该类包含要显示到 QTableViewdata() 调用的实际数据(由 Model::data() 访问)

我的班级监听网络数据并在单独的线程上运行,从该线程更新它的数据(简单的固定大小的 10 个字符串数组)。

我的班级中的数据必须通过不断更新它的线程和 Qt GUI 通过在 Model 上调用 data() 来访问。

我假设我需要使用互斥锁来同步对我的字符串数组的访问,但QAbstractTableModel::data() 是一个const 方法,所以我无法将boost::mutex 锁定在其中。

在扩展QAbstractTableModel并向QTableView提供数据的类中同步访问数据的一般模式是什么?

【问题讨论】:

【参考方案1】:

我认为 Qt 的项目视图类(如 QAbstractTableModel)和多个线程不能很好地结合在一起。问题是 QAbstractTableModel 类希望在每次数据更改时通知所有关联的视图类,并且视图类希望能够随时从数据模型中读取数据。如果更新和数据由不同的线程拥有,那么实现这一点将很难(无论如何是有效的)。我怀疑您提出的任何多线程解决方案都需要大量序列化,以至于两个线程中只有一个线程最终会同时运行,此时您实际上已经回到单线程程序,只需一个非常复杂的设计:)

如果可能的话,我的建议是将您的 10 字符串数据库移到主/Qt 线程中。您的网络操作也可以移到主线程中(使用 QSocketNotifier 对象并确保 I/O 都是非阻塞的,这样它就不会阻止 Qt 事件循环并损害 GUI 性能);或者您可以将网络保持在单独的网络线程中,并让网络线程向主/Qt 线程发送更新消息,告诉主/Qt 线程如何更新数据库/表模型。关键是让主/Qt线程完成对数据模型数据库的所有读取和写入。

【讨论】:

我第一次尝试使用 Qt 的模型/视图是在多线程代码库中,并想“嗯……是的,这似乎不起作用。” lists.qt.nokia.com/pipermail/qt-interest/2009-August/… Net 类包含我的业务逻辑并使用第三方库进行联网,因此我更喜欢将其与 Qt 模型分开(Qt 模型/视图设计文档建议类似的方法)。数据不属于不同的线程,而是在不同线程的回调中访问。我锁定数据只是为了读/写几个字符串值,到目前为止它似乎工作。我在 Model::data() 处理程序中将 const 与互斥锁进行类型转换,以便能够读取数据。 Qt 中似乎有很多东西可以在可爱的小例子中使用,但需要大量连接真实世界的代码。 @HostileFork 我看过你的链接讨论 - 这周我构建了简单的模型/视图 Qt 应用程序(我通常不做 gui 应用程序,我更喜欢网络,更喜欢 Cocoa /Mac 然后 Qt/Linux)显示 2 个表,每个表 3x10 的数据(格式化为字符串的双精度值)。该模型具有内部类,该类使用另一个具有自己的队列(我假设运行它自己的线程)的第 3 方网络库来从网络中获取数据。白天,我每分钟接近 4000 次全表更新 x2(来自 2 个来源的相同数据),每条消息都会更新表中的所有项目......到目前为止对我有用。

以上是关于Qt:如何在模型/视图设置中同步对来自多个线程的数据的访问?的主要内容,如果未能解决你的问题,请参考以下文章

在不同的线程中拥有 Qt 只读模型和视图

QT 模型/视图项目不显示来自 QList 的字符串

Qt4 模型/视图 - 在视图中转换数据?

Qt OpenGL 数据同步/模型/视图实现

在 MVC4 中的单个视图中访问多个模型中的项目

同步处理来自多个线程的数据