尽管有线程,Qt GUI 仍挂起
Posted
技术标签:
【中文标题】尽管有线程,Qt GUI 仍挂起【英文标题】:Qt GUI hangs despite threading 【发布时间】:2019-04-13 10:26:38 【问题描述】:我有一个 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. 我该如何解决?
我见过manysimilarquestion,但大多数都是关于QThread
,所以我无法解决我的问题。
【问题讨论】:
评论不用于扩展讨论;这个对话是moved to chat。 【参考方案1】:原来问题是我使用QFileSystemModel
(不是在这个函数中,而是在一般情况下)显示文件夹中的文件列表,this 回答指出:
QFileSystemModel
列出后台线程上的目录以避免 阻止用户界面。但是,一旦它获得更新列表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
被设置回可能是最佳方式。
【讨论】:
如果model
是您的QFSM,则不允许在GUI 线程之外触摸它,无论您对其施加的锁定量是多少。您需要从 GUI 线程本身“禁用”它。
@peppe 我该如何禁用它?
来自产生线程的函数(所以,基本上,来自 GUI 线程本身)。或者,从工作线程发出信号/使用排队调用。
@peppe 除了更改 rootPath 之外,有没有办法禁用 QFSM?以上是关于尽管有线程,Qt GUI 仍挂起的主要内容,如果未能解决你的问题,请参考以下文章