Problem implementing runTaskWithProgressBar(te::ThreadPoolJobWithProgress& job)

Hi,
I’m struggling with implementing the UIBehaviour::runTaskWithProgressBar(te::ThreadPoolJobWithProgress& job) method for displaying a progress bar while rendering a track. The idea is to overlay the progress bar on top of the main component and updating it after every call to job.runJob(). The problem is that the progress bar gets not displayed until the job is finished. My current workaround is to call MessageManager::getInstance()->runDispatchLoopUntil(1) every few calls of job.runJob(). This is however not a good way I think, but I’m not able to come up with a better solution. Can anyone maybe help out? Would be much appreciated.
My current code looks something like this:

void runTaskWithProgressBar(te::ThreadPoolJobWithProgress& job) override
    {
        if (auto topLevelWindow = dynamic_cast<ResizableWindow*>(TopLevelWindow::getActiveTopLevelWindow()))
        {
            if (auto component = dynamic_cast<MainComponent*>(topLevelWindow->getContentComponent()))
            {
                double progress = job.getCurrentTaskProgress();
                component->ShowProgressBar(progress);

                for (int i = 0; job.runJob() == ThreadPoolJob::jobNeedsRunningAgain; ++i)
                {
                    progress = job.getCurrentTaskProgress();

                    if (i % 100 == 0)
                        MessageManager::getInstance()->runDispatchLoopUntil(1);
                }

                component->HideProgressBar();
            }
        }
    }

Where component->ShowProgressBar(progress) creates the ProgressBar, adds it and makes it visible and calls resized() on the MainComponent, and component->HideProgressBar() destroys it and again calls resized().

Thanks in advance, greetings!

You can’t call job.runJob() on the main thread, or your UI will not respond, as you are seeing. You need spawn a thread which calls job.runJob() in a loop.

Then runTaskWithProgressBar needs to wait until the thread is finished while pumping message loop.

Rough code to implement:

    void runTaskWithProgressBar (ThreadPoolJobWithProgress& t)
    {
        TaskRunner runner (t);

         while (runner.isThreadRunning())
             if (! MessageManager::getInstance()->runDispatchLoopUntil (10))
                 break;
    }

//==============================================================================
struct TaskRunner  : public Thread
{
    TaskRunner (ThreadPoolJobWithProgress& t) : Thread (t->getJobName()), task (*t)
    {
        startThread (4);
    }

    ~TaskRunner()
    {
        task.signalJobShouldExit();
        waitForThreadToExit (10000);
    }

    void run() override
    {
        while (! threadShouldExit())
            if (task.runJob() == ThreadPoolJob::jobHasFinished)
                break;
    }

    ThreadPoolJobWithProgress& task;
};

You’ll need to add whatever updates your UI.

2 Likes

Thanks so much for your quick Response, I’m gonna try that.