QabtractItemModel线程安全
QAbstractItemModel thread safety
我对QAbstractItemModel
的实现正在听某些事件,并且在单独的线程中处理更新。更新的处理可能会导致模型中的布局和/或数据更改。数据本身的存储为boost::mutex
-受保护,QAbstractItemModel
的接口函数的每个调用(如果我正确理解,在GUI线程中执行),并且更新处理功能(在单独的线程中)锁定了Mutex。可以在锁定数据()/rowcount()/任何可能同时尝试获取的data()/rowcount()/dataChanged的信号时发出信号吗?
一块代码:
class MyItemModel : public QAbstractItemModel {
Q_OBJECT
public:
void processUpdate(const Update& update) {
Mservice.post([this, update]() {
boost::lock_guard<boost::mutex> lock (Mlock);
bool willModifyLayout = checkWillModifyLayout(update)
bool willModifyData = checkWillModifyData(update);
if (willModifyLayout) {
emit layoutAboutToBeChanged();
}
Mdata.processUpdate(update);
if (willModifyLayout) {
emit layoutChanged();
}
else if (willModifyData) {
emit dataChanged();
}
});
}
virtual QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE {
boost::lock_guard<boost::mutex> lock (Mlock);
if (index.isValid()) return Mdata.data(index, role);
}
private:
boost::mutex Mmutex;
boost::asio::service Mservice;
boost::asio::thread MserviceThread;
DataStorage Mdata;
}
找到了我自己问题的答案:如果该模型属于其他QThread,则该模型的信号将使用QT :: QueuedConnection连接到视图,这很好。但是,如果(默认情况下)该模型属于GUI qthread(又称qcoreApplication :: instance() -> thread()),则将立即执行模型的插槽,从而导致data(columtCount(),columtCount(),等等,,没关系。
QAbstractItemModel
是不是线程安全。
这主要是因为跨线的信号被排队。
想象包含QList<int> list;
的模型的以下方案(忽略QModelIndex
):
background thread GUI thread + signal queue, abbreviations for readability
[MODEL] [VIEW] ( )
beginInsertRows(0, 1); ... ( rowsAboutToBeAdded(0, 1) = add(1) )
list << item(); (doing ( add(1) )
endInsertRows(); something ( add(1), rowsAdded(0, 1) = added(1) )
beginRemoveRows(0, 1); else) ( add(1), added(1), rowsAboutToBeRemoved(0, 1) = rem(1) )
list.removeAt(0); ... ( add(1), added(1), rem(1) )
endRemoveRows(0, 1); ... ( add(1), added(1), rem(1), rowsRemoved(0, 1) = rmvd(1) )
rowsAboutToBeAdded(0, 1); ( added(1), rem(1), rmvd(1) )
rowsAdded(0, 1); ( rem(1), rmvd(1) )
possible crash!
原因:
在rowsadded()中,视图将迟早致电
model()->data(model()->index(0, 0));
此模型索引无效,因为该模型没有行。
在最好的情况下,它只是返回无效的QVariant()
。
在最坏的情况下(无防御检查),该模型试图访问list[0]
。
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 如何将元素添加到数组的线程安全函数?
- C++中的线程安全删除
- 在std::thread中,joinable()然后join()线程安全吗
- 在c++队列中使用pop和visit实现线程安全
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 全局变量 多读取器 一个写入器多线程安全?
- 共享队列的线程安全
- boost::文件系统::recursive_directory_iterator多线程安全
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 以线程安全的方式转换 C/C++ 中时区名称字符串的时区偏移量
- 线程安全运算符<<
- 如何使缓存线程安全
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 提升精神 V2 Qi 语法线程安全吗?
- 线程调用的函数对对象删除是否安全?
- asio 链对象线程安全吗?
- 线程安全队列 c++
- 提供对不同类型的数据(建议、代码审查)的线程安全访问的类
- 有没有更好的方法可以使此代码线程安全?线程局部静态似乎是一个生硬的工具