The ProgressBar control and loops go hand-in-hand. If there is a ProgressBar on a Window, you can bet a For loop is close by. But there are right and wrong ways to do this, and most of the time I see progress code, I see the wrong way. It'll look something like the following, inside the action event of a PushButton:
But this is very, very bad code.
Why is it so bad?
In short, your app locks up entirely while the loop is doing its work. The user interface only updates once all your code is finished, so buttons will not be clickable, windows will not be movable, menus not be usable, etc. The OS will probably even list your app as "not responding" if your code takes more than a few seconds to complete. So your user experience suffers.
It's also slower. The Refresh call demands the ProgressBar be redrawn before the next line of code is triggered. This is wasted effort as the ProgressBar doesn't need to update so frequently.
Experienced users may have heard all this before. But there are also more subtle reasons this code is awful. On Windows 7 and Vista, ProgressBars now animate from their previous value to the new value. Since you're locking up your app while processing however, the ProgressBar can never animate, so it will always appear to be one "step" behind.
And in Web projects, the situation is even worse. WebControls have no Refresh method. All user actions, such as a push of a button, get a single "payload" of data to send back to the browser. If we included such a method, the first call to Refresh would work, but then we use up our one payload, and all following UI updates will never reach the browser.
Doing it right
The answer is the Thread class. To oversimplify, Threads allow you to execute code that does not get in the way of the UI update code. However, you absolutely must not interact with any controls from within the Thread. This poses an obvious problem for updating a ProgressBar. That problem is solved by a Timer. The setup is a little on the tedious side, but it is necessary.
Both objects can be placed on any Window, WebPage, or Container. Create a property on your Window called Progress As Integer. In your Thread1.Run event, put the following code:
In this sample code, we're not doing any actual work. Yours will of course. Rather than attempting to update the ProgressBar directly, we update the Progress property so the timer can know how much work has completed. And speaking of your timer, use this code for its Action event:
We use the timer to update the ProgressBar. There is no need for a Refresh call, because the ProgressBar will redraw automatically when the Timer Action event completes. If the ProgressBar is full, the work is done, so we turn off the Timer. And lastly, to start the work, use this code:
We first reset the Progress property, just in case. Then "turn on" the Timer so it updates the ProgressBar frequently while the work is being done, and finally actually start the work by calling Thread1.Run. Now all you need to do is update Timer1's properties to adjust the rate you want to ProgressBar to update. On a Desktop app, you can easily get away with a Period of 250. On a Web app, you'll want to slow it down though. A minimum of Period of 1000 is strongly recommended, though I would use 2000 personally. Set Timer1.Mode to Off, there's no need to update the ProgressBar if nothing is happening.
You could also turn all this into a handy reusable class.
That's it. Your ProgressBar will update nicely, your app will be a "good citizen" and your users will be happier.