I have a pool of computational tasks which run in async mode.
Each time a thread competes its task an atomic int is increased by 1.
After launching my threads I run this function to see the progress bar showing how many tasks have been completed.
bool updateProgressBar(ON_wString progressBarText, std::atomic<int>* barCurrentProgress, int totalWork)
{
int pollingTime = 10;
// initializing Rhino progress bar
CRhinoDoc* doc = RhinoApp().ActiveDoc();
doc->StatusBarProgressMeterStart(0, totalWork, progressBarText, true, true);
doc->StatusBarProgressMeterPos(barCurrentProgress->load(), true);
// start polling the jobs progress at a pollingTime(ms) rate
for (;;)
{
int currentProgress = barCurrentProgress->load();
RhinoApp().Wait(0);
//doc->StatusBarProgressMeterPos(barCurrentProgress->load(), true);
doc->StatusBarProgressMeterPos(currentProgress, true);
// exit when all jobs have finished
//if (barCurrentProgress->load() == totalWork)
if (currentProgress == totalWork)
{
doc->StatusBarProgressMeterPos(totalWork, true);
doc->StatusBarProgressMeterEnd();
return true;
}
// wait some for some time before polling again
std::this_thread::sleep_for(std::chrono::milliseconds(pollingTime));
}
return false;
}
It works well. However, when running a heavier set of tasks the progress bar was moving slower and I managed to notice that when all tasks are completed I get in if (currentProgress == totalWork) as expected, but the lines:
are not executed. Setting a breakpoint I see that currentProgress == totalWork but the bar shows less and it does not disappear until the calling function exits.
I thought that this has to do with synchronization. So changed the code with:
While I do not know much about c++, I do know that in Rhino when doing async tasks, calling RhinoApp.Wait() gives the Rhino UI thread an opportunity to pump the messages to the UI to repaint the screen, etc.
So in my world I might do an Invoke to marshall the update of the UI to the UI thread. You are likely accomplishing something similar in your logic.
You can probably get away with just doing 1 of those calls after the StatusBarProgressMeterEnd(), rather than doing both calls to wait.
I have a rather old machine and after some testing I realize that even in a for loop (without async) when trying to show, update or end the progress bar I always have to add RhinoApp().Wait(0); to make the progress bar function properly.
Especially in a loop you need to give the UI time to update. So that isn’t necessarily something unique to your CPU speed. Anytime you want “UI” to be updated you have to all Rhino to pump messages to the UI, which is what RhinoApp.Wait() accomplished.
Hence, should I just try and test what is the minimum value that works? In this case could it be that an older machine requires more wait time than a new one?
I suspect it may need slightly more time on slower machines, however if going from 0 to 1 “fixed” it for you. You may be able to just set it to 100 ms and be fine.
No need to overcomplicate things.
Just bare in mind if you are in a loop the time will be a factor of the iterations through the loop…