尽管有线程,但Qt GUI仍然挂起

时间:2019-04-13 10:26:39

标签: c++ multithreading qt user-interface

我有一个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.我该如何解决?

我见过many similar question,但是大多数都与QThread有关,所以我无法解决问题。

1 个答案:

答案 0 :(得分:2)

原来的问题是我正在使用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放回原处可能是最佳方法。