我有一个Qt GUI应用程序,当按下按钮时,它会执行一些I/O绑定工作。为了避免 GUI 没有响应,我创建了一个新线程并将工作移到那里:
private slots:
inline void on_process_button_clicked() const
{
std::thread thread(&My_class::on_process_button_clicked_real_work, this);
thread.detach();
}
我立即拆下线程。另一个函数只是做真正的工作:
void on_process_button_clicked_real_work() const
{
std::lock_guard<std::mutex> lock(mutex);
// Some irrelevant code ...
}
GUI 现在没有完全冻结,我仍然可以看到它更新了,但它变得非常无响应和滞后。
问题:
1. 为什么会这样?
2. 我该如何解决?
我见过很多类似的问题,但大多数都是关于QThread
所以我无法解决我的问题。
事实证明,问题是我正在使用QFileSystemModel
(不是在此函数中,而是在一般情况下(来显示文件夹中的文件列表,并且此答案指出:
QFileSystemModel
列出后台线程上的目录以避免 阻止 UI。但是,一旦它获得更新列表QFileSystemModelPrivate::_q_fileSystemChanged
然后获取 主线程中文件的图标使用QFileInfoGatherer::getInfo()
反过来调用QFileIconProvider::icon(QFileInfo)
.
问题是QFileSystemModel
不断更新 GUI,而新线程快速创建/删除文件,这会导致体验滞后。我不知道如何停止或延迟该模型中的更新,但我所做的是将rootPath
更改为""
并在函数完成工作后将其更改回来:
void on_process_button_clicked_real_work() const
{
std::lock_guard<std::mutex> lock(mutex);
auto path = model.rootPath();
model.setRootPath("");
// Some irrelevant code ...
model.setRootPath(path);
}
实现某种类型的锁定对象是异常安全的,并确保rootPath
被设置可能是最佳方法。