首页| 论坛| 消息

标题:QFileSystemWatcher监控某个目录下千万级文件变化时导致主界面卡顿的问题
作者:lwei24
日期:2023-04-12 11:09
内容:

如题,用QFileSystemWatcher监控某个指定的目录变化,若拷贝1000张图片到该监控目录,则会出现QFileSystemWatcher对象一下子触发很多个同一信号,这个信号对应一个同一槽函数,槽函数主要处理该信号获取的图片文件信息集合并发送给主线程,开启子线程,将图片信息同步更新到QTableView表格的模型上,具体代码如下:
//CustomTableView.h
class CustomTableView : public QTableView
{
Q_OBJECT
public:
CustomTableView(QWidget *parent = nullptr);
void addWatchPath(QString path);
signals:
void startUpdateDirectory(int type, QString diskPath, QList recordList, QStringList curFileNameList, QString newFileName);
private:
QThread*m_fsThread;
FSWatcherWorker*m_fsWorker; //继承QObject
QFileSystemWatcher *m_fsWatcher;
CustomTableModel *m_customTableModel; //自定义模型,继承QAbstractTableModel
QMap m_currentContentsMap; // 当前每个监控的内容目录列表
QListm_recordList; //监控目录的集合,FileInfo为监控目录下文件或文件夹的信息,例如名称、大小、修改时间等。
};
//CustomTableView.cpp
CustomTableView::CustomTableView(QWidget *parent)
:QTableView(parent)
{this->addWatchPath("E:\\test\\");}

void CustomTabl ..


#1 [20091001753 04-12 12:10]
qt 界面的绘制就在主线程,你想界面不卡也很简单,把密集型任务不要放到主线程处理,或者说,尽可能的不要把业务放在主线程处理。
例如你可以将 QFileSystemWatcher 放在其他线程。
其次,你可以设置缓冲,例如目录更新后,你就记载这个目录更新了。但是真正对目标目录处理的函数,只会每秒处理一次。
因为比如你复制很多小文件,这些文件可能1秒内复制了几百个,那你执行几百次更新目录犯不着,每秒处理一次就好。
甚至,你可以等改文件夹1秒内没有新的动作(稳定后)再更新目录。这适合于不是每时每刻都在更新的文件夹,而一旦他在更新,等他更新结束再去处理就好。
而且这个更新的步骤,例如涉及到文件的复制粘贴,也可以是放在其他线程的。
#2 回 20091001753 的帖子 [lwei24 04-12 13:44]
20091001753:qt 界面的绘制就在主线程,你想界面不卡也很简单,把密集型任务不要放到主线程处理,或者说,尽可能的不要把业务放在主线程处理。
例如你可以将 QFileSystemWatcher 放在其他线程。
其次,你可以设置缓冲,例如目录更新后,你就记载这个目录更新了。但是真正对目标目录处理的函 .. (2023-04-12 12:10)
多谢版主,您说的将 QFileSystemWatcher 放到子线程,我试试看。还有就是设置缓冲,我是否可以理解成延时等待。至于您说的等1s目录没有新动作再更新目录,这个可以有,只是等它更新结束再去处理,可能有些难,因为QFileSystemWatcher这个类好像没有提供关于任何检测更新动作是否结束的标志或接口,单单从延时等待1秒没有新动作去判断,恐怕有点难判断。
#3 [20091001753 04-12 14:41]
QHash map,分别是目录与更新时间
directoryChanged 的信号:map=QDateTime::currentDateTime();
这样你就构建了一个有变化的目录,及该目录最后的更新时间,精确到毫秒的。
然后创建一个定时器,每秒检查这个 map
auto cur = QDateTime::currentDateTime();//获取最新的时间
for(auto& :map)//检查 map,这个需要c17支持,然后对比 cur 与 v 相差超过1秒或多秒就执行更新,更新后把这个目录从 map 里删掉就好。
只要思想不滑坡,办法总比困难多。
#4 回 20091001753 的帖子 [lwei24 04-12 15:10]
20091001753:QHash map,分别是目录与更新时间
directoryChanged 的信号:map=QDateTime::currentDateTime();
这样你就构建了一个有变化的目录,及该目录最后的更新时间,精确到毫秒的。
....... (2023-04-12 14:41) 
哈哈哈,多谢版主,我考虑到拷贝文件的大小不确定,所以觉得拷贝单个文件的时间就不确定,姑卡在不知道用几秒执行更新目录合适,不过您说思路我会好好想想再试试看效果的。

回复 发表
主题 版块