Aykhan Hagverdili
Aykhan Hagverdili

Reputation: 29955

Qt GUI hangs despite threading

I have a Qt GUI application which does some I/O bound work when a button is pressed. In order to avoid GUI not being responsive, I created a new thread and move the work there:

private slots:
    inline void on_process_button_clicked() const
    {
        std::thread thread(&My_class::on_process_button_clicked_real_work, this);
        thread.detach();
    }

I detach the thread immediately. The other function simply does the real work:

void on_process_button_clicked_real_work() const
{
    std::lock_guard<std::mutex> lock(mutex);

    // Some irrelevant code ...
}

The GUI now doesn't entirely freeze, I can still see it updated, but it becomes really unresponsive and laggy.

Questions:
1. Why does this happen?
2. How may I fix it?

I have seen many similar question, but most are about QThread so I couldn't solve my problem.

Upvotes: 0

Views: 475

Answers (1)

Aykhan Hagverdili
Aykhan Hagverdili

Reputation: 29955

Turns out the problem is I was using QFileSystemModel (not in this function but in general) to show a list of files in the folder and this answer points out:

QFileSystemModel lists directories on a background thread to avoid blocking the UI. However, once it gets a list of updates in QFileSystemModelPrivate::_q_fileSystemChanged it then fetches the icons for the file in the main thread using QFileInfoGatherer::getInfo() which in turn calls QFileIconProvider::icon(QFileInfo).

The problem is that QFileSystemModel constantly updates the GUI while the new thread rapidly creates/removes files and that causes the laggy experience. I don't know how to stop or delay updates in that model, but what I did is changing rootPath to "" and changing it back once the function finishes the work:

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);
}

Implementing some kind of lock object to be exception safe and make sure the rootPath is set back is probably the most optimal way.

Upvotes: 2

Related Questions