Gino Pensuni
Gino Pensuni

Reputation: 366

Will UI block when waiting for QThread / How to use QThread properly

If I have a progressbar in the ui thread (window), which shall run endless until a method finishes it's work, will the ui thread block and so the progress bar if I'm waiting for a second QThread to finish? If the ui thread blocks waiting, then i would not to wait for the second thread. I thought to implement a callback method which will be called when the second thread finished, but then: How can i connect to the callback method?

What do I want to do? I have a window, this window has a progressbar which is first not visible. When the user presses a certain button to request data, a method will be called which returns a RequestPointer which contains a method which returns the request status. When the user presses the button, i want to make the progress bar visible, running infinitely till the request is finished and i can print the data to the window. To the Worker i want to pass this pointer and the worker checks in a while (flag) loop, if the status is still running and sleep if so. When the worker finishes, i want to stop the progressbar and make it unvisible again. Do i have to pass the progress bar to the thread, or can i wait for the thread without blocking the ui?

I'm not quite a Qt pro. Really new to it. I tried to get some info from the https://doc.qt.io/Qt-5/qthread.html website, but it's a bit hard for me to understand the code example.

Method in my worker class:

void Worker::watchRequest(RequestPtr r_ptr)
{
    bool exit = true;

    while (!exit)
    {
        ErrorCode errorCode = r_ptr->Test();

        switch (errorCode)
        {
        case Request_RUNNING:   
            QThread::msleep(10);
            break;
        case Request_ABORTED:
            exit = true;
            break;
        case Request_SUCCESS:
            exit = true;
            break;
        }

    }

Upvotes: 0

Views: 1199

Answers (3)

Rhnbmpl
Rhnbmpl

Reputation: 88

To update the UI Thread's progress bar while the operation is running, use a QTimer object to increment the progress bar's value (Max value will be :One less than Progress bar's value when the operation completes). Also connect the QThread to a slot by Signal/Slot method to signal the UI thread when the operation has ended. When the QThread finishes the operation, send a signal to a Slot in the UI Thread, which will set the final value of the progress bar and also stop the QTimer.

Upvotes: 0

Aconcagua
Aconcagua

Reputation: 25536

QThread has a finished signal. Connect this one to some appropriate slot, which will trigger any action necessary on thread completion.

I suppose best candidate to know how far the progress went is the worker thread itself. You might create your own signal that sends the current progress to some slot that will do the update of the progress bar appropriately.

Alternatively, you might use a QTimer to read the current progress from time to time (this resembles closer to what you have now, but does not block the UI).

Upvotes: 2

Benjamin Bihler
Benjamin Bihler

Reputation: 2073

If you don't want to block the user interface, all you have to do is to call QApplication::processEvents(); in your while-loop.

I have some code which uses std::future instead of QThread and my code looks like this:

while (!progressIndicator->UserBreak()
    && (future.wait_for(std::chrono::seconds(0)) != std::future_status::ready))
{
    QApplication::processEvents();
}

This works well.

Upvotes: 1

Related Questions