我可以在QThread中使用与QAbstractTableModel数据的交互吗?

时间:2012-04-19 06:54:02

标签: qt qt4 qthread qabstractitemmodel qabstracttablemodel

我知道我们不能在非GUI线程中使用GUI交互(QThread)。 但是我不知道我们是否可以或不能在线程中与模型(QAbstractItemModel)进行交互,如果是True,那么如何以正确的方式进行交互?

我老老实实地在Google和SO上搜索过一些关于此内容的内容,似乎我的问题没有相关的答案。

1 个答案:

答案 0 :(得分:2)

“与模特互动”是什么意思?如果您希望通过直接操作来从多个线程访问模型,则必须序列化对模型的访问。由于模型中有很多方法,我建议你不要在模型中添加一个互斥体 - 它会非常繁琐且容易出错,因为忘记一个互斥锁更容易。相反,使用模型继承QObject的事实,因此可以接受事件。

  1. 你的gui线程直接访问模型。
  2. 其他线程通过向其发布事件(以及可能接收回复事件)与模型进行交互。
  3. gui线程将以任何其他访问方式串行处理这些事件,从而保护您的模型免受并发访问。
  4. 其他线程当然可以通过事件接收模型的回复。你有两个事件基类:一个Request类,用于从模型中请求事物,然后有一个Response事件基类,模型将用它来回复。 Request类应该有一个QObject* sender成员,以便模型知道将回复事件发布到哪个QObject。您可能希望请求和回复都带有相同的标识符(比如串行递增int),以便可以匹配请求和响应。

    您必须通过事件实现与模型交互的所有线程代码,而不是通过重新实现QThread::run(),而是在QObject中实现。实例化QObject后,只需将其移动到单独的线程即可。 QThread的run()默认实现将旋转一个事件循环,以便在有任何事件,信号或定时器准备就绪时保持QObject的执行。零持续时间计时器是一种保持线程永久忙碌的方法,但请确保您不会一次性处理太多,否则您将延迟处理传入事件。

    您也可以使用信号和插槽,但不能直接调用它们,您只能:

    1. connect()给他们,
    2. 使用QMetaObject::invokeMethod通过Qt::QueuedConnection调用它们。
    3. 通过在主线程上下文中执行的仿函数(例如,lambda)来调用它们;请参阅this answer了解如何操作。
    4. 在幕后,当您将信号连接到位于不同线程中的QObject的插槽时,Qt会创建一个连接,将每个信号编组为QMetaCallEvent,然后在带有目标插槽的QObject的线程中解组它住。