QAbstractItemModel 线程安全 [英] QAbstractItemModel thread safety
问题描述
我的 QAbstractItemModel
实现正在监听一些事件,并在一个单独的线程中处理更新.更新的处理可能会导致模型中的布局和/或数据更改.数据本身的存储是 boost::mutex
- 受保护的,每次调用 QAbstractItemModel
的接口函数(如果我理解正确,在 GUI 线程中执行),并且更新处理函数(在单独的线程中)锁定互斥锁.在锁定 data()/rowCount()/whatever 可能同时尝试获取的相同互斥锁的同时发出信号 layoutChanged/dataChanged 是否可以?
My implementation of QAbstractItemModel
is listening to some events, and processes updates in a separate thread.
Processing of an update may lead to layout and/or data change in the Model.
The storage of the data itself is boost::mutex
- protected, every call of QAbstractItemModel
's interface functions (executed, if I understand correctly, in GUI thread), and the update processing functions (in a separate thread) lock the mutex.
Is it okay to emit the signals layoutChanged/dataChanged while locking the same mutex that the data()/rowCount()/whatever may be trying to acquire at the same time?
一段代码:
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;
}
推荐答案
找到了我自己问题的答案:如果 Model 属于不同的 QThread,那么这个 Model 的信号会通过 Qt::QueuedConnection 连接到 view,就可以了.但是如果(默认情况下)Model 属于 GUI QThread(又名 QCoreApplication::instance()->thread()),Model 的 slot 将被立即执行,导致对 data()、columnCount() 等的调用,因此,这不行.
Found answer to my own question: If the Model belongs to a different QThread, then the signals of this model will be connected to view using Qt::QueuedConnection, and it's fine. But if (by default) the Model belongs to GUI QThread (a.k.a. QCoreApplication::instance()->thread()), the slot of Model will be executed immediately, causing calls to data(), columnCount(), etc, thus, it's not okay.
这篇关于QAbstractItemModel 线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!