QAbstractItemModel 线程安全 [英] QAbstractItemModel thread safety

查看:57
本文介绍了QAbstractItemModel 线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆