我知道我们不能在非 GUI 线程(QThread
)中使用 GUI 交互。但我不知道我们是否可以或不能与QAbstractItemModel
线程中的模型()进行交互,如果为真,那么如何以正确的方式进行交互?
老实说,我在谷歌和 SO 上搜索了一些关于这个的东西,似乎我的问题没有相关的答案。
我知道我们不能在非 GUI 线程(QThread
)中使用 GUI 交互。但我不知道我们是否可以或不能与QAbstractItemModel
线程中的模型()进行交互,如果为真,那么如何以正确的方式进行交互?
老实说,我在谷歌和 SO 上搜索了一些关于这个的东西,似乎我的问题没有相关的答案。
“与模型交互”是什么意思?如果您的意思是要通过直接操作从多个线程访问模型,那么您必须序列化对模型的访问。由于模型中有很多方法,我建议您不要在模型中添加互斥锁——这会非常乏味且容易出错,因为很容易忘记互斥锁储物柜。相反,使用您的模型继承 QObject 的事实,因此可以接受事件。
其他线程当然可以接收来自模型的回复——也可以通过事件。您将有两个事件基类:一个Request
用于从模型请求事物的类,然后是一个Response
模型将用于回复的事件基类。Request 类应该有一个QObject* sender
成员,以便模型知道要将回复事件发布到哪个 QObject。您可能希望请求和回复都带有相同的标识符(例如连续递增的 int),以便可以匹配请求和响应。
QThread::run()
您必须通过事件而不是通过重新实现,而是在 QObject 中实现与模型交互的所有线程代码。实例化 后QObject
,只需将其移至单独的线程即可。run()
如果有任何事件、信号或计时器准备好,QThread 的默认实现将旋转一个事件循环以保持您的 QObject 执行。零持续时间计时器是一种保持线程永久忙碌的方法,但请确保不要一次性进行太多处理,否则会延迟传入事件的处理。
也可以使用信号和槽,但不能直接调用,只能:
connect()
给他们,QMetaObject::invokeMethod
通过with调用它们Qt::QueuedConnection
。在幕后,当您将信号连接到位于不同线程中的 QObject 的插槽时,Qt 会创建一个连接,将每个信号编组为 a QMetaCallEvent
,然后在具有目标插槽的 QObject 所在的线程中将其解组。