Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Refreshing window 3

Status
Not open for further replies.

sjulian

Programmer
Aug 15, 2000
56
US
My code has a form that I show using "frmConversionStatus.Show vbModeless"
It has a progress bar, a label and a listbox. At the bottom of each loop in a module, I update the progress bar value and the label caption.
At various points during execution, the window will stop refreshing.
When running in the development environment, I can use Ctrl+Break to pause the execution and then resume it and the window will resume refreshing for a while. The code continued to execute while the screen was "frozen"
When running the compiled exe, the screen "freezes" but I can look at my output and see that it is continuing to grow.
To the user though, it will appear that the app has gotten stuck.
How can I get the window to continue to refresh?
 
put a Doevents directly after the progress bar value and the label caption updates inside the loop.

"If I were to wake up with my head sewn to the carpet, I wouldn't be more surprised than I am right now.
 
Depending on how many loops you do, it may be prudent to only perform the DoEvents say every 100th iteration as each call to DoEvents passes control back to Windows to do other stuff. If you're only doing 100 or 1000 Iterations it doesn't matter so much as you won't notice a significant slowing in your program, but if you're doing many thousands or millions of iterations you will certainly notice the effect. Seeing as how you're already using a progress bar, you could interrogate the progress bar count and use the Mod function to perform a DoEvents if the remainder is 0. Again, this method is OK for smaller iterations, but for large iterations I'd recommend a separate counter as it is quicker to access than the property of a control.
HTH
Walter
 
Updating the progressbar on every iteration will slow the code down too so better pop that behind the Mod condition along with the DoEvents.

Private Sub Command1_Click()

Const totaliterations& = 100000000
Dim iteration&

For iteration = 1 To totaliterations
If iteration Mod (totaliterations \ 10) = 0 Then 'gives 10 updates
ProgressBar1.Value = iteration / totaliterations * 100
DoEvents
End If
Next

End Sub
 
Thanks to all of you; I have been looking for ways to speed up this code and I'm sure this will make a difference.
 
I have been looking for ways to speed up this code and I'm sure this will make a difference.
Guess again.

This just breaks your program's stranglehold on the Windows event loop, so the user gets to see that Windows is alive.
 
yeah... DoEvents actually slows down the system. It is forcing the application to Pause so that all items on the stack can be completed (ie: Repaint the progress bar, update labels, move a window, load web page). Once the stack has processed everything, DoEvents releases and the program continues. However, while the application is technically not going as fast, with the system being released and the progress bar being updated, the user will "feel" as though it is moving faster since there is something happening on the screen.

"If I were to wake up with my head sewn to the carpet, I wouldn't be more surprised than I am right now.
 
harebrain, what will speed me up is not refreshing the progress bar each loop
 
Yes it will. Any time you make the application have to re-paint a control/form it is going to move slower. Especially inside a tight loop. Drop the progress bar and any labels/etc that may be updating with values. Signify on your form that processing is in progress at the beginning and then fire a msgbox when complete. This will let the users know that something is being done and to be patient.

"If I were to wake up with my head sewn to the carpet, I wouldn't be more surprised than I am right now.
 
Not to put too fine a point on it, sjulian, (OK, well, maybe) but nothing here so far is going to "speed up" your code. What has been discussed is keeping the user engaged and techniques to minimize performance degradation while doing so. As soonerjoe points out, both manipulating a progress bar and yielding the CPU through DoEvents actually slow you down.
 
While it's not exactly relevant, it's maybe worth mentioning that the other option here is to only refresh the progress bar once a second rather than on every 10 times around the loop, since if the loop hardly does anything it might still be refreshing the progress bar thousands of times a second.

Here's what I'd do:

Code:
NextUpdate = DateAdd("S", 1, Now)
For...
  ' Do stuff here...
  If (Now > NextUpdate) Then
    ProgressBar1.Value = ...
    NextUpdate = DateAdd("S", 1, Now)
    DoEvents
  End If
Next

Note that this code is NOT a good example of being a good Windows citizen because it'll hog the CPU and only allow other apps to get a look in once every second. However, it's a good trade-off based on the original question since it only updates the progress bar once a second and devotes the rest of the time to doing whatever's in the loop.

It'd be better to put the DoEvents outside of the If..Then if you want to be other-app-friendly.

- Andy
___________________________________________________________________
If you think nobody cares you're alive, try missing a couple of mortgage payments
 
As long as all we want is for the progress bar to be refreshed, why don't we just use the control's Refresh method instead of DoEvents?
 
In the original version, the form was being refreshed each time the progressbar's value was updated. Eventually the form would just "freeze". The DoEvents was suggested to overcome the freeze.
 
I think you'll find that most people here thought they were solving a tight loop issue; that's certainly what I thought the problem was. So just to confirm, you were already using ProgressBar1.Refresh and Label1.Refresh, and it froze?
 
You are correct. Can you tell me how I mis-led you so I won't make the mistake again?
Thanks
 
You didn't mislead. You simply didn't mention that yoiu were already using the Refresh methods of the ProgressBar and the Label at any point in this thread until right now.

Now, here's the problem. In simple terms, Refresh is a superlightweight version of DoEvents in that the only messages it processes from the message queue are paint messages (and then only those for the control we are refreshing). So if Refresh is being frozen out it is likely that DoEvents - a much more dangerous way of getting controls repainted - will be at some point as well.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top