Progressbar, containercontrol and threads

I’m having a hard time trying to update a progress bar.

I need to process a heavy array of container controls and want to update a progress bar in the mean time, doing it on the loop directly doesn’t works (as expected) but I can’t use a thread because I need to process the UI (container control) on the run event and this generates an exception.

I have tried to use the Task class (from examples) and process the UI on the UpdateUI method (using args) but in this case the progress bar instantly finishes and my process continues in the background, logic because the run does nothing except incrementing progressbar value.

I have also tried to use DoEvents because it doesn’t matter that UI is not available if I can inform the user it is busy but can’t seem to get it working right. Please notice that the whole processing loop may take more than a minute on an average computer.

Any help will be appreciated.

Difficult to help without much details. You say the progress bar does not update from within the loop. Is it because the loop is inside an event that will not update the UI before it is complete ? Have you tried ProgressBar.Invalidate ?

Alternatively, you may simply want to update the ProgressBar from a timer that looks at a value you set in the loop.

DoEvents is not recommended in UI apps at all.

The loop is in a method of the main window, code is like:

ProgressBar1.maximum = MyCCArray.Ubound For n as integer = 0 to MyCCArray.ubound ProgressBar1.value = n ProgressBar1.invalidate ProcessCC(n) next n

This doesn’t updates the progress bar and there is no difference if I include DoEvents.

If I place

ProgressBar1.value = n ProgressBar1.invalidate App.DoEvents

inside a deep level of ProcessCC (this method calls others) then it updates the progress bar.

I have tried alternative ways with timers and they don’t work correctly, always the timer is faster than the process and progress bar ends before the job has finished.

As I really prefer to “freeze” the app until this job has ended, which issues may I have using DoEvents?

I have no idea what ProcessCC does but this updates the progressBar just fine :
toto is a method of the window called from a button action event

Sub toto() For n as integer = 0 to ProgressBar1.Maximum ProgressBar1.value = n ProgressBar1.invalidate 'ProcessCC(n) pause(30) next n End Sub

pause is a method that waits for a number of ticks to have elapsed ; here it pauses for half a second

Sub pause(po as integer) dim deja as integer = ticks while ticks < deja+po wend End Sub

This code does freeze the app until the method is over, but the ProgressBar is updated. Once again, it is difficult to know what maybe going on without the full picture.

As for DoEvents, read http://documentation.xojo.com/index.php/DoEvents
Using DoEvents in a GUI application will likely cause instability.

Thanks Michel.
Yes, the sample you provide works fine, but as soon as some database writing and graphics manipulation are involved it seems the process is too busy to update the progress bar.
Sometimes it starts fine and at 40% I become (in Windows) the “Not responding” title and progressbar freezes.

From my understanding, Invalidate will not always work because it waits to update the control when there is “free time” and not necessarily immediately. Refresh on the other hand immediately updates the control. Try this code instead:

ProgressBar1.maximum = MyCCArray.Ubound For n as integer = 0 to MyCCArray.ubound ProgressBar1.value = n ProgressBar1.Refresh //change this line ProcessCC(n) next n

[quote=120731:@Alejandro Fresno Meyer]Thanks Michel.
Yes, the sample you provide works fine, but as soon as some database writing and graphics manipulation are involved it seems the process is too busy to update the progress bar.
Sometimes it starts fine and at 40% I become (in Windows) the “Not responding” title and progressbar freezes.[/quote]

You should try Jason King’s refresh suggestion first. Then eventually if it still does not work add Application.YieldToNext right after the refresh to allow the UI update. It should do the same as DoEvents without the risks.

I have tried both, first using Refresh instead invalidate and it doesn’t works. Then I have changed DoEvents to YieldToNext and it neither works.
Progress stops at around 40%, window freezes and “not responding” comes.

Adding DoEvents all works fine, progress bar finishes, I can even move the window or use another feature of the application.