views:

19

answers:

2

Hi, I'm having a weird issue with form painting in the Compact Framework. I have a login dialog that is basically a small form that is opened on top of another using ShowDialog. When a card is swiped, the login dialog is supposed to close, then some login tasks are performed and then the form behind it should be activated. The problem is that the form behind the login dialog is not being refreshed and so the login dialog will not be removed until after the form behind is refreshed by some user action. This is probably due to the heavy processing that goes on in the login tasks part, but I've not found a way to solve this.

Basically, I want a way to force the application to close the dialog and paint everything again, before performing the heavy login tasks. I've tried numerous refresh methods without any luck:

Form loginDialog = new Form();
DialogResult result = loginDialog.ShowDialog();
loginDialog.Dispose();

//I've tried everything at this point to get the form to refresh before performing
//login tasks
this.Refresh();
this.Invalidate();
Application.DoEvents();


PerformHeavyLoginTasks();

Does anyone know what could be going wrong? Thanks

A: 

Ok I figured this out. The problem was with a custom control on the background form that manually paints itself using rectangles and such. I think this is a compact framework bug since I called Refresh and Invalidate on that control as well and it should've repainted. I had to create a method that would call the control's OnPaint override directly since Invalidate and Refreshed were pretty much ignored.

JayPea
A: 

The issue, I believe, is that you're not fully understanding what's going on system-wise here.

When your fore window (the Dialog) is dismissed, the background window (the Form) is given focu and tol to repaint the clipping region where the dialog was. This happens via a PostMessage call, which sends a Windows Message that has to be popped, translated and dispatched down in the bowels of the Application.Run call.

This is, by design, a fairly slow process as the UI should not be preempting things that are important.

If you are doing heavy processing immediately after that PostMessage happens, the processing of those windows messages can often be slowed, ending up with the UI appearing "locked" or drawing really slowly. This is exacerbated if the processing you're doing is on the same thread as the UI.

Why are your efforst not making things better?

  • Calling Refresh simply sends another message. That message now gets in line for processing, so it would actually make things worse.
  • Calling Invalidate does pretty much the same this as Refresh, just asynchronously. Again, it makes things worse.
  • DoEvents tells the message pump to pop, translate and dispatch a message. That dispatch still has to be processed on the UI thread, so noting is going to happen until the thread has time to do the work (i.e. after your processing)

So how do we "fix" this?

The first step is often to put the processing on a separate thread to allow the scheduler to round-robin tasks between the UI and processing threads, up to the default quantum. Thgis means that the processing can only starve the UI for a maximum of 100ms before some sort of drawing is allowed to occur (assuming equal thread priority).

new Thread(PerformHeavyLoginTasks)
{
    IsBackground = true
}.Start();

You can go a step further and give the UI a "jump start" on the processing (of 10ms in this example):

new Thread(new ThreadStart(delegate
    {
        Thread.Sleep(10);
        PerformHeavyLoginTasks();
    }))
{
    IsBackground = true
}.Start();

Of course this may mean you need to now handle the next "display" asynchrously if the UI you want to display is dependent on the processing result. There are plenty of online resources for async patterns, so I won't beat that dead horse here.

ctacke
Thanks for your response, it is good to know how that process works since I was pretty much guessing. In this case I found a way to force the control to paint itself before going into the heavy processing, but I'm sure that this info will come in handy.
JayPea

related questions