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