I am in inexperienced programmer who has an application that displays many (50-60) controls on a form.
The application is a production planning system, that requires many controls displayed on screen (1 for each job qued on individual machines)
Whenever the form is re-draw, it is painfully slow, I have set the doublebuffer ControlStyles etc, but are unable to fix the issue.
This issue is running on a P4 2.8GHZ / 500MB PC.
Can anyone assist
I have attached an example of my problem (not my actual application, but the samle gives the same issue). The sample simply displays many controls onto a form. When you force a redraw ie ALT-TAB to another app and back again, the screen redraws very slowly.
Aaron
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim p As Panel Dim t As Label Dim y, x As Integer Dim switch As Boolean Me.SetStyle(ControlStyles.UserPaint, True) Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True) Me.SetStyle(ControlStyles.DoubleBuffer, True) Me.SetStyle(ControlStyles.UserPaint, True) Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True) Me.SetStyle(ControlStyles.DoubleBuffer, True) Me.UpdateStyles() For x = 1 To 13 For y = 1 To 17 p = New Panel p.Parent = Me p.Width = 80 p.Height = 50 p.Name = "p" & x & y p.Location = New Point(81 * x, 51 * y) If switch Then p.BackColor = Color.Red switch = False Else p.BackColor = Color.Blue switch = True End If t = New Label t.BackColor = Color.White t.Width = 40 t.Height = 15 t.Parent = p t.Text = "test" t = New Label t.BackColor = Color.White t.Location = New Point(50, 30) t.Width = 40 t.Height = 15 t.Parent = p t.Text = "test2" t = New Label t.BackColor = Color.White t.Location = New Point(5, 30) t.Width = 40 t.Height = 15 t.Parent = p t.Text = "test3" Next y Next x End Sub
Slow screen redraw
Rohit Nayak
I'm a little excited. I did make a few optimizations, ones that I really do not think are important AND I built it release mode and NGEN'ed it. It worked incredibly well. Startup is normal and those colors just roar onto my screen.
Don't forget the JIT slows you in the beginning and this where you get the largest gains by Ngening!
The NGEN command batch file looked like this:
windir%\Microsoft.NET\Framework\v2.0.50727\ngen /delete Test2.exe
%windir%\Microsoft.NET\Framework\v2.0.50727\ngen test2.exe Test2.exe
%windir%\Microsoft.NET\Framework\v2.0.50727\ngen test2.exe /show
For those who are not familiar with Ngen here is a reference:
http://msdn.microsoft.com/msdnmag/issues/06/05/CLRInsideOut/default.aspx
Please note: I have a pretty fast machine.
istrasci
Here is what I have....
Public Class Form1< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Protected size1 As New Size(80, 50)
Protected size2 As New Size(40, 15)
Protected point1 As Point = New Point(50, 30)
Protected point2 As Point = New Point(5, 30)
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.Visible = False
Me.Cursor = Cursors.WaitCursor
Dim p As Panel
Dim t As Label
Dim y, x As Integer
Me.Size = New Size(1063, 910)
Dim switch As Boolean
For x = 0 To 12
For y = 0 To 16
p = New Panel
p.Parent = Me
p.Size = size1
p.Name = "p" & x & y
p.Location = New Point(81 * x, 51 * y)
If switch Then
p.BackColor = Color.Red
switch = False
Else
p.BackColor = Color.Blue
switch = True
End If
t = New Label
t.BackColor = Color.White
t.Size = size2
t.Text = "test"
t.Parent = p
t = New Label
t.BackColor = Color.White
t.Location = point1
t.Size = size2
t.Parent = p
t.Text = "test2"
t = New Label
t.BackColor = Color.White
t.Location = point2
t.Size = size2
t.Parent = p
t.Text = "test3"
Next
Application.DoEvents()
Next
Me.Visible = True
Me.Cursor = Cursors.Default
End Sub
Craig Humphrey
Hi there, thanks for your input, the (setstyle) method was (after some initial investigation) an attempt to fix the issue.
But the issue is exactly the same whether I use Me.SetStyle / or just Setstyle / or leave out the Setstyle lines all together.
Tejas Zaveri
Renee, I tried you modified code on my old, slow P4 3.0Ghz system and it was as slow as as the original............for me. Not too sure why. I just woke up a couple hours ago. Still need more coffee!! I agree that with so many controls being drawn on the screen it is always going to be slow. GDI+ is probably the best way to work with this. And another is to split the number of controls up over more than one form. I doubt that a user can view this many controls on a single form easily and be able to make effective use of them. If this is to monitor some sort of input from an external device or other function, I would , as I said, split them up, add some kind of notification on the main form , make the form flash or something, when a control on the other form needs some sort of attention.
james
aka:Trucker
ygermain
Your loops begin with 1 which you don't see much of in Dot Net. A Next is all that's required at the end of a For statement.
13 * 17 is 221. Your creating 221 of these controls in that loop not to mention the panels they are in. that's a lot of work. And they don't update until the end. Try... putting an Application.DoEvents outside the inner loop. I wouldn't think this would do anything, but it's still a good test.
Igor K.
Here you go, much faster and not as annoying to the user:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Me.Visible = False Me.Cursor = Cursors.WaitCursor Dim p As Panel Dim t As Label Dim y, x As Integer Dim switch As Boolean 'Me.SetStyle(ControlStyles.UserPaint, True) 'Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True) 'Me.SetStyle(ControlStyles.DoubleBuffer, True) 'Me.SetStyle(ControlStyles.UserPaint, True) 'Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True) 'Me.SetStyle(ControlStyles.DoubleBuffer, True) 'Me.UpdateStyles() For x = 1 To 13 For y = 1 To 17p =
New Panelp.Parent =
Mep.Width = 80
p.Height = 50
p.Name =
"p" & x & yp.Location =
New Point(81 * x, 51 * y) If switch Thenp.BackColor = Color.Red
switch =
False Elsep.BackColor = Color.Blue
switch =
True End Ift =
New Labelt.BackColor = Color.White
t.Width = 40
t.Height = 15
t.Parent = p
t.Text =
"test"t =
New Labelt.BackColor = Color.White
t.Location =
New Point(50, 30)t.Width = 40
t.Height = 15
t.Parent = p
t.Text =
"test2"t =
New Labelt.BackColor = Color.White
t.Location =
New Point(5, 30)t.Width = 40
t.Height = 15
t.Parent = p
t.Text =
"test3" Next yApplication.DoEvents()
Next x Me.Visible = True Me.Cursor = Cursors.Default End SubI set the form to not visible in the Form_Load event and then a Wait cursor. I then commented out the SetStyle stuff and at the end of the inside loop, I used Renee's suggestion and set Application.DoEvents() and then after the controls were drawn to the form, I set the form's visiable property back to True and the cursor to Default.
Works pretty fast compared to the code you posted.
james
aka:Trucker
Weidong Ding
notjosh
Lets think practically: That's a lot of controls...yes, yes, they may be necessary, but if the user is going to have to deal with all those controls it's going to take the user a good few minutes to deal with them: the second or so to draw them isn't an issue.
These are very complex controls - a button isn't just a button anymore (especially not a windows 3.1 button - and wow: Windows 3.1 was blazing fast on a Pentium II). It's a complex rendering. Unfortunately, cool software features always stays ahead of hardware capability (Transprency in forms is really cool, but you know, when I want to get work done, I really could care less about the shadowing and being able to see 'through' my work - I've stopped using the opacity in forms :) however, used appropriately, it works - i.e. breaking on errors in the VS IDE)
If speed is an issue, you will have to sacrifice the convenience (of the buit in controls): use GDI+ to draw your controls, it'll be (relatively) fast. By using GDI+ you will be controlling exactly the features you need in the graphical representation. I worry about speed constantly, but appropriately: if speed actually brings something to the table, then spend the time. If it needs to get done tomorrow, then don't worry about it.
Actually, I tend to use such things as a rule of thumb: if the redraw rate of the screen is slowing down, then the form is too complicated.
MichaelJosten
Ummm, Ken, this sounds great... but I don't see a suspend and resume update. I do a suspend and resume layout. It looks a tiny bit slower to me.
Mark Durley
Hey Trucker!!!
I'm sure mileages will vary.... and my system is only 3.2 Ghz but it's hyper threaded which really does make a difference.
I think my large gains came from Ngenning. However, I agree with what you and say also.
There is no disagreement there.
AndrewBadera
arvas
wow trucker....
I fixated upon the loops and overlooked the set styles... but a form should not be visible until either it finishes the load routine or until it executes its first Application.Doevents.
But way to go!!!
Toni Leitao - MS
zlobish
Thanks, but, it still draws slower than it should. I think the problem is in the loops. And I believe that the code can be trimmed down to make it faster. But, right now, I'm too sleepy to mess with it enough to do anything constructive. Have a good night!
james
aka:Trucker