tags:

views:

180

answers:

4

I currently have an application that spawns multiple instances of a single win form. Each instance of the form has a timer which updates a number of controls and some of the properties of the form itself at rate of approx 1 tick/sec. Once the application reaches a certain number of forms it stops painting the 'updates' that occur within the timer ticks.

I want to hold the UI thread at the bottom of the timer and allow the form to repaint without calling Application.DoEvents (my understanding is that Application.DoEvents() handles all pending window messages across the application (which could include other timers 'ticks'? - not sure) when all I want it to process is the redrawing of the form now that a number of the controls have been updated).

+4  A: 

If you just want the form or a specific control to redraw itself, just call Control.Refresh on the form/control in question.

That being said, this is usually (like Application.DoEvents) a sign that a redesign is in order. If you have long running processes like this, it's a much better idea to push the work into a BackgroundWorker, which will make the actual computational work run in a background thread, and prevent the UI from becoming unresponsive.

Reed Copsey
thanks for that. I have a status bar message updating 2-3 times during a "configuation" button click and thought I needed doEvents to flush the messages. But the refresh is great.
Joe
+4  A: 

It's not clear to me why you want to call DoEvents at all. Why not just let the window repaint itself appropriately? What's wrong with the way it behaves at the moment?

Calls to DoEvents usually indicate that something should be in a background thread - in your case it sounds like it might actually just be that you've got too many events going on. If your GUI is so complex that it can't redraw itself in a second, it sounds like that's probably a design issue with the UI itself.

Jon Skeet
+2  A: 

There are three categories of Windows messages that are dispatched by the message loop and a call to Application.DoEvents(). First are messages that are sent with SendMessage(). They are important, they need to be dispatched right away because there is some other program waiting on the result of the SendMessage() call. They are not put on the message queue, Windows calls the window procedure directly.

Then there are messages that are put on the message queue with PostMessage(). They can wait, they are merely notifications. All of the keyboard and mouse messages fit that category.

Then there are the low priority messages, WM_TIMER and WM_PAINT. They only get dispatched when there's nothing else to do, no SendMessage is pending and the message queue is empty.

Sounds like you got yourself into a situation where you starving Windows so badly that it can't get around to dispatching those low priority message anymore. Probably neither getting timer Ticks nor Paint events anymore. Calling DoEvents only once a second will certainly do that. This is bad, your program is now affecting the operation of other programs as well. You'll have to fix that. Do so by re-architecting your app so you no longer depend on DoEvents.

Hans Passant
A: 

My 2c:

Having a timer in each form is going to slow down performance to a crawl. Each window at each second interval is going to request the application to switch to that window's "context" and execute some code. That whole switch is likely longer than your code actually takes to run. Couple that with the likely fact that all of your forms are in the same "context".

Instead consider something like this if possible:

List<MyForm> listofmyform;

Timer t = new Timer()
t.tick += delegate
{
    foreach(MyForm thisform in listofmyform)
        thisform.DoUpdate();
}

This only uses one timer to update all of your forms, only requires one "context switch" and will likely cure some performance problems you're having.

Dearmash