January 7, 2005
As a followup to my caution about exceptions in Form.Paint(), I wanted to illustrate why this technique is so effective. Let's say you had a form with this code:
Private IsFirstPaint As Boolean = True
Private Sub DoWork()
Cursor = Cursors.WaitCursor
StatusBar1.Text = "Loading..."
For i As Integer = 0 To 99
ComboBox1.Items.Add("ComboBoxItem " & i)
ComboBox1.SelectedIndex = 4
For i As Integer = 0 To 99
ListBox1.Items.Add("ListBoxItem " & i)
ListBox1.SelectedIndex = 4
StatusBar1.Text = "Ready."
Cursor = Cursors.Default
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Private Sub Form1_Paint(ByVal sender As Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) _
If IsFirstPaint Then
IsFirstPaint = False
So either we're doing 5 seconds of work in Paint, or we're doing 5 seconds of work in form Load. Here's what it looks like when the work is done in Form.Load:
And here's what it looks like when the work is done in Form.Paint:
The amount of time is the same in both cases, but guess which one users will tell you is "faster"? Perceived performance is more important than actual performance.
Sure, you can do a lot better job with threading, but I guarantee that'll take a lot more work than three lines of code! That's why I love the IsFirstPaint and DoEvents combo: maximum benefit for minimum effort.
Posted by Jeff Atwood
Those little gif movies are so awesome/effective - what did you use to make them?
I've used Gif-gif-gif in the past, which is positively ancient but still works fine and produces very tiny GIFs:
now I use Camtasia studio, which is a great product and far more flexible. Also more expensive, but it can render to flash or AVI as well, and with some neat options like sound/visual effects for keypresses and mouseclicks:
Interesting. That does appear to work, and the debugger picks up the correct line of code in Load() exceptions, too.
So, the moral of the story is:
Always call this.Show() in the Form_Load event?
I'll have to go back and add this to my last project. There are several instances where a dialog will appear after a few seconds of waiting, causing the user to usually try to open it 2 or 3 times.
I wouldn't say "always" because we don't know if there are any side-effects yet. But yes, if you have a form that does a few seconds (or more) worth of work, I'd say try one of the Paint() or Load() DoEvents techniques first as a quick easy solution. If you need *real* threaded background processing, then look into the BackgroundWorker solution.
Anyway definitely try it and post your feedback here. I'd try it in our project but that's in offshore mode now. I'm disinclined to make a bunch of sweeping changes in the way we display forms..
Couldn't you achieve the same effect by calling either Application.DoEvents() or this.Refresh() in the Form_Load event?
Just answered my own question. DoEvents and Refresh do nothing until the form is visible. So how about this.Show() in Form_Load? I tested it, and it appears to do the same thing as the Form_Paint solution above, and it's only one line of code.
The only problem that I see is that there may be some way to load a form without showing it, although I don't know of any. This "trick" would affect that. I would say that the this.Show() solution would work for most, if not all situations.
I know this is a relatively ancient post, but I'm going through your past posts one by one.
The technique I've always used is to have this kind of code in the Form_Activate event, with a boolean called DoneIt = false initially, set to true inside Form_Activate after the test. Is there a reason to prefer the Paint event?