.NET Questions (CLOSED)

Questions and Answers on any aspect of .NET. Now closed.

This discussion group is now closed.

Have a question about .NET development? Try stackoverflow.com, a worldwide community of great developers asking and answering questions 24 hours a day.

The archives of .NET Questions contain years of Q&A. Even older .NET Questions are still online, too.

Window redraw

What's the secret to getting Dot Net/C# to refresh the screen while performing a computation-intensive task, or waiting for a database call? I have some longish proceedures (e.g. 5 minutes) and if the user checks their email (or whatever) and covers the window (which may have cues to the progress of the proc), it is not redrawn until the end.
Peter Vanderwaart Send private email
Tuesday, July 11, 2006
 
 
Use a background worker thread to do the computationally expensive task. In .NET 2.0 there is a new BackgroundWorker object that makes this really easy. If you are using .NET 1.1 you can Google for BackgroundWorker and you will find some 1.1 implementations. Or you can roll your own. This is by far the best way to handle this type of situation.
anon
Tuesday, July 11, 2006
 
 
And be sure to ignore any advice that tells you to use DoEvents. It is dangerous if not handled correctly. If someone presses the close button and then you call DoEvents, the result is a real mess if you don't handle every little possbile scenario.
anon
Tuesday, July 11, 2006
 
 
Sounds like a good reason to proceed with the upgrade to 2.0.  Thanks for the help.

Am I the only one who thinks the Microsoft should have worked this out in the foundation? I don't have a long history working in the Windows GUI, but over 5 years and three or four development environments, this is the only one that I have found that doesn't redraw when the frame is reselected as active.
Peter Vanderwaart Send private email
Tuesday, July 11, 2006
 
 
I'd like to hear more about the amazing GUI frameworks that redraw windows while the main thread that pumps messages is locked up doing computations.
Chris Send private email
Tuesday, July 11, 2006
 
 
I will elaborate one particular case to be clear, so you know exactly what my complaint is. I have a process with a loop. Within the loop is the usual mix of calls to the DBMS, computations, and a line gets written to a file. At the end of the loop, there is a ProgressBar.PerformStep() to keep the user informed.

If the user starts the process and leaves the computer untouched, the ProgressBar marches across the window. But if the user covers the window and then uncovers it, the ProgressBar remains frozen until the process concludes.

(This is not a ProgressBar issue. The behavior is the same with other updates to the info on the screen.)

So I am not complaining about the window being nonresponsive during a lengthy call to the DBMS or during long calculations that don't affect visible objects. I understand those situations. But I don't understand why the program fails to update the window as it should after being reselected. I don't recall that behavior fom Powerbuilder or Java.
Peter Vanderwaart Send private email
Wednesday, July 12, 2006
 
 
One thing you can always do is call the Refresh method on the progressbar control. This causes the update to the progress bar to occur immediately. I use this with text boxes and such when I want to show status during a loop. But keep in mind that this technique should only be used with simple controls and short loops. The real solution to long running loops is to use the BackgroundWorker component.

As for any other language causing the update to occur immediately, they are just automatically calling the platform equivalent of the Refresh method after you change the control property. This ability is built into Win32. The default is not to update controls immediately since this causes additional overhead. And from what I remember, PowerBuilder worked the same way as .NET does. It had an equivalent method that you could call (but it's been a while since I worked with it so I could be wrong).
anon
Wednesday, July 12, 2006
 
 
A simple call to ProgressBar.Refresh() does not rescue the situation. Incidently, I only update the bar every 100 iterations of the loop to reduce overhead.
Peter Vanderwaart Send private email
Wednesday, July 12, 2006
 
 
It has to do with the nature of windows and how it updates. Under the hood, there's a message loop. When the window is "damaged" (other window moved on and then off it), the OS posts a message to that window's message queue.

Inside every windows application is a loop that looks for messages on that queue. It processes each message, then goes back and idles waiting for a new one.

Here's the problem - while you're off doing the 5-minute db call, your application is NOT CHECKING THE MESSAGE QUEUE. As a result, it's not handling the underlying WM_PAINT message, and your screen doesn't get redrawn.

Updating the progress bar isn't showing this problem becuase the update call causes the bar to redraw right then and there.

The solution here is, as others have mentioned, to do long running work on a separate thread.
Chris Tavares Send private email
Wednesday, July 12, 2006
 
 
>  Within the loop is the usual mix of calls to the DBMS, computations, and a line gets written to a file. At the end of the loop, there is a ProgressBar.PerformStep() to keep the user informed.

If you were doing this in C++ you would also want a GetMessage/DispatchMessage loop near where you call PerformStep(): this would be to ensure that any Window messages queued for the application's windows are dispatched.

What's the .NET equivalent of GetMessage/DispatchMessage?
Christopher Wells Send private email
Thursday, July 13, 2006
 
 
No simple equivalent because WinForms completely hides the message loop.  You can get at the raw message loop by overriding some method or attaching some event or something (sorry, please check MSDN Library)... but seriously, you shouldn't be doing this.  Just use a background thread, it's the right thing to do.
Chris Nahr Send private email
Thursday, July 13, 2006
 
 
The 'Application.DoEvents()' method seems to be (based on its documentation) the method that you should want to call: try calling that before and/or after each time you call 'ProgressBar.Refresh()'.
Christopher Wells Send private email
Thursday, July 13, 2006
 
 
NO NO NO NO NO! DO NOT CALL DoEvents! EVER!

Are you crazy? This opens a whole can of reentrance worms. I wished this method wasn't even available. It should be hidden by default, just like the WinMain procedure. :(
Chris Nahr Send private email
Friday, July 14, 2006
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz