| 
UID:202628
注册时间2020-05-17最后登录2025-01-07在线时间456小时
发帖399搜Ta的帖子精华0
金钱5945威望440贡献值0好评度360
访问TA的空间加好友用道具
     | 
 
如题,用QFileSystemWatcher监控某个指定的目录 变化,若拷贝1000张图片 到该监控目录,则会出现QFileSystemWatcher对象一下子触发很多个同一信号,这个信号对应一个同一槽函数,槽函数主要处理该信号获取的图片文件 信息集合并发送给主线程 ,开启子线程,将图片信息同步更新到QTableView 表格的模型上,具体代码如下: //CustomTableView.h class CustomTableView : public QTableView{    Q_OBJECTpublic:    CustomTableView(QWidget *parent = nullptr);    void addWatchPath(QString path);    signals:    void startUpdateDirectory(int type, QString diskPath, QList<FileInfo> recordList, QStringList curFileNameList, QString newFileName);    private:    QThread                      *m_fsThread;    FSWatcherWorker              *m_fsWorker;         //继承QObject    QFileSystemWatcher           *m_fsWatcher;    CustomTableModel             *m_customTableModel; //自定义模型,继承QAbstractTableModel    QMap<QString, QStringList> m_currentContentsMap; // 当前每个监控的内容目录列表    QList<FileInfo>                  m_recordList;         //监控目录的集合,FileInfo为监控目录下文件或文件夹的信息,例如名称、大小、修改时间等。};//CustomTableView.cpp CustomTableView::CustomTableView(QWidget *parent):QTableView(parent){this->addWatchPath("E:\\test\\");}void CustomTableView::addWatchPath(QString path){    m_fsWatcher = new QFileSystemWatcher();    connect(m_fsWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(onDirectoryChanged(QString)));    // 添加监控路径    m_fsWatcher->addPath(path);    // 如果添加路径是一个目录,保存当前内容列表    QFileInfo file(path);    if (file.isDir())    {        const QDir dirw(path);        m_currentContentsMap[path] = dirw.entryList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files, QDir::DirsFirst);    }    m_fsThread = new QThread(this);    if(m_fsWorker == NULL)    {        m_fsWorker = new FSWatcherWorker;        m_fsWorker->moveToThread(m_fsThread);        connect(m_fsThread, &QThread::finished, m_fsWorker, &FSWatcherWorker::deleteLater);        connect(m_fsThread, &QThread::finished, this, &CustomTableView::setFsWorkerNull);        connect(m_fsWorker, &FSWatcherWorker::updateDir, this, &CustomTableView::onUpdateDir);        connect(this, &CustomTableView::startUpdateDirectory, m_fsWorker, &FSWatcherWorker::startFSWatcherWork);//startFSWatcherWork获取文件信息并发送更新集合        connect(this, &CustomTableView::cancelUpdateDirectory, m_fsWorker, &FSWatcherWorker::cancelFSWatcherWork);        m_fsThread->start();    }}void dCustomTableView::onDirectoryChanged(QString path){    // 比较最新的内容和保存的内容找出区别(变化)    QStringList currEntryList = m_currentContentsMap[path];    const QDir dir(path);    QStringList newEntryList = dir.entryList(QDir::NoDotAndDotDot  | QDir::AllDirs | QDir::Files, QDir::DirsFirst);    QSet<QString> newDirSet = QSet<QString>::fromList(newEntryList);    QSet<QString> currentDirSet = QSet<QString>::fromList(currEntryList);    // 添加了文件    QSet<QString> newFiles = newDirSet - currentDirSet;    QStringList newFile = newFiles.toList();    // 文件已被移除    QSet<QString> deletedFiles = currentDirSet - newDirSet;    QStringList deleteFile = deletedFiles.toList();    // 更新当前设置    m_currentContentsMap[path] = newEntryList;    if (!newFile.isEmpty() && !deleteFile.isEmpty())    {        // 文件/目录重命名        if ((newFile.count() == 1) && (deleteFile.count() == 1))        {            DEBUG_PRINT(FALSE, QString("directory updated: %1, File Renamed from %2 to %3").arg(path).arg(deleteFile.first()).arg(newFile.first()));            emit startUpdateDirectory(0, m_watchPath, currEntryList, newEntryList);        }    }    else    {        // 添加新文件/目录至Dir        if (!newFile.isEmpty())        {            DEBUG_PRINT(FALSE, QString("directory updated: %1, New Files/Dirs added: %2").arg(path).arg(QString::number(newFile.size())));            foreach (QString file, newFile)            {                // 处理操作每个新文件....                if(!file.isEmpty())                {                    emit startUpdateDirectory(1, m_watchPath, m_recordList, currEntryList, file);                }            }        }        // 从Dir中删除文件/目录        if (!deleteFile.isEmpty())        {            DEBUG_PRINT(FALSE, QString("directory updated: %1, Files/Dirs deleted: %2").arg(path).arg(QString::number(deleteFile.size())));            foreach(QString file, deleteFile)            {                // 处理操作每个被删除的文件....                if(!file.isEmpty())                {                    emit startUpdateDirectory(-1, m_watchPath, m_recordList, currEntryList,file);                }            }                    }    }}void dCustomTableView::onUpdateDir2(int size, FileRecord record){    if(size > 0)    {        m_recordList.push_back(record);        m_customTableModel->updateData(m_recordList);        //此处更新模型数据,即具体updateData代码为{this->beginResetModel();m_recordList = recordList;this->endResetModel();}    }    if(size == 0)    {        m_recordList.clear();        m_customTableModel->removeRows(0, m_customTableModel->rowCount());        m_customTableModel->updateData(m_recordList);    }}
如上代码,在运行过程中,拷贝1000个文件到指定监控目录下,主界面 从拷贝的那一刻开始到刷新QTableView表格上的模型的时间很卡,其中这段时间,将1000张照片完全拷贝完到监控目录大概时间40s到60s左右,而刷新QTableView模型就大概8分钟到10分钟左右,这个是测试的日志分析的。各位大佬们,你们有什么办法可以优化这个问题 吗?在线等,欢迎各位大佬们指点一二,小弟感激不尽。    
 |