EnableVisualStyles and DoEvents

G

Guest

I've noticed that calling DoEvents is much slower in an application that has called Application.EnableVisualStyles in Sub Main. Furthermore, the performance seems to worsen each time that DoEvents is called.

To demonstrate what I'm experiencing, create an app with a Sub Main, a Main Form, and a Button (called Button1). Include the following code in Sub Main:

Application.EnableVisualStyles
Application.DoEvents
Application.Run(New MainForm)

Now, include the following code in the Click event handler of Button1:

For i As Integer = 1 to 8000
Application.DoEvents
Next i

On my system the first time that I click Button1 takes ~0.92 seconds. Subsequent clicks take 1.35, 1.73, 2.12, and 2.52 seconds. But, if I now remove Application.EnableVisualStyles from Sub Main, then clicking Button1 only takes ~0.07 seconds (and the time does not increase if I continue to click Button1).

Is this a known issue? Is there a fix? Would it help to enable visual styles via a manifest file rather than calling EnableVisualStyles?

I'm using .NET Framework v1.1 on Windows XP Pro (SP1).

Thanks,
Lance
 
B

Brian Henry

it's getting worse because of how your calling it is pileing up stuff on the
GDI message queue and causeing it to load up with to much... don't call it
so close to each other, there really is no nead for that


Lance said:
I've noticed that calling DoEvents is much slower in an application that
has called Application.EnableVisualStyles in Sub Main. Furthermore, the
performance seems to worsen each time that DoEvents is called.
To demonstrate what I'm experiencing, create an app with a Sub Main, a
Main Form, and a Button (called Button1). Include the following code in Sub
Main:
Application.EnableVisualStyles
Application.DoEvents
Application.Run(New MainForm)

Now, include the following code in the Click event handler of Button1:

For i As Integer = 1 to 8000
Application.DoEvents
Next i

On my system the first time that I click Button1 takes ~0.92 seconds.
Subsequent clicks take 1.35, 1.73, 2.12, and 2.52 seconds. But, if I now
remove Application.EnableVisualStyles from Sub Main, then clicking Button1
only takes ~0.07 seconds (and the time does not increase if I continue to
click Button1).
Is this a known issue? Is there a fix? Would it help to enable visual
styles via a manifest file rather than calling EnableVisualStyles?
 
M

Mattias Sjögren

Is this a known issue? Is there a fix?

Why is it an issue at all, and what needs to be fixed? DoEvents can
take any amount of time, depending on how many messages you have
queued up. So if you make any assumptions on the time it will take to
complete, you're asking for problems.

I don't see why anyone would call DoEvents 8000 times in a loop in any
real code.



Mattias
 
T

Tom Leylan

It sounds like a reasonable question doesn't it?

I note on one blog that the following was posted "If you're using v1.1 of
the Framework and encounter an SEHException and have no idea what's causing
it, check to see if you called Application.EnableVisualStyles(). Apparently
that is the source for a number of problems that appear as SEHExceptions."

And on another "It would appear that due to a bug in EnableVisualStyles you
have to call Application.DoEvents after the call to
Application.EnableVisualStyles or your image lists won't work properly any
more. Hope this helps someone. Posted by Simon at September 24, 2003 04:53
PM"

And on a third "It would appear that due to a bug in EnableVisualStyles you
have to call Application.DoEvents after the call to
Application.EnableVisualStyles or your image lists won't work properly any
more. Hope this helps someone. Posted by Simon at September 24, 2003 4:53
PM"

Ultimately I found this which explains much of it:

http://weblogs.asp.net/rprabhu/archive/2003/09/28/56540.aspx

It doesn't matter if the guy noticed it calling DoEvents 8000 times
something is up and that revealed one of the problems. What would the
alternative be to post 3000 lines of code and as you to run it for an hour?
:)

I'll bet $10 that we don't get a belated reply from one of the MS guys
thanking us for the question. :)
 
J

Jay B. Harlow [MVP - Outlook]

Lance,
On my system the first time that I click Button1 takes ~0.92 seconds.
Subsequent clicks take 1.35, 1.73, 2.12, and 2.52 seconds.
But, if I now remove Application.EnableVisualStyles from Sub Main,
then clicking Button1 only takes ~0.07 seconds
(and the time does not increase if I continue to click Button1).
How are you timing this? Which version of VS.NET (2003 or Whidbey)?

In VS.NET 2003 under Windows XP Pro, I get the following numbers:

With EnableVisualStyles:
Sum: 0.715197881294964
Avg: 8.93997351618705E-05
Min: 4.77714346376425E-05
Max: 0.150142546049847
Count: 8000
StDev: 0.00168651269805306
Var: 2.84432508069421E-06

Without EnableVisualStyles:
Sum: 0.105847251536168
Avg: 1.3230906442021E-05
Min: 8.93968367488047E-06
Max: 0.00417790529243242
Count: 8000
StDev: 8.3665359383228E-05
Var: 6.9998923607247E-09

Even with EnableVisualStyles: yes the numbers are larger, however they are
definitely sub second times in both cases!

Looking at the XML file created it appears that the numbers drop off (it
speeds up) after about 30 iterations, in both cases.

BTW: Here is the code I used to get the above numbers:

Declare Function QueryPerformanceCounter Lib "Kernel32" (ByRef X As
Long) As Short
Declare Function QueryPerformanceFrequency Lib "Kernel32" (ByRef X As
Long) As Short

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim frequency As Long
QueryPerformanceFrequency(frequency)

Dim ds As New DataSet("DoEvents")
Dim dt As New DataTable("DoEvents")
dt.Columns.Add("start", GetType(Long))
dt.Columns.Add("finish", GetType(Long))
dt.Columns.Add("seconds", GetType(Double))
dt.Columns.Add("time", GetType(Long), "finish - start")
ds.Tables.Add(dt)
Dim start, finish As Long
For i As Integer = 1 To 8000
QueryPerformanceCounter(start)
Application.DoEvents()
QueryPerformanceCounter(finish)
Dim seconds As Double = (finish - start) / frequency
dt.Rows.Add(New Object() {start, finish, seconds})
Next i
ds.WriteXml("DoEvents.xml")
Debug.WriteLine(dt.Compute("Sum(seconds)", Nothing), "Sum")
Debug.WriteLine(dt.Compute("Avg(seconds)", Nothing), "Avg")
Debug.WriteLine(dt.Compute("Min(seconds)", Nothing), "Min")
Debug.WriteLine(dt.Compute("Max(seconds)", Nothing), "Max")
Debug.WriteLine(dt.Compute("Count(seconds)", Nothing), "Count")
Debug.WriteLine(dt.Compute("StDev(seconds)", Nothing), "StDev")
Debug.WriteLine(dt.Compute("Var(seconds)", Nothing), "Var")
End Sub

Personally, this seems to be largely academic, DoEvents processes all the
events in you Win32 message queue, which means you have no real control over
how long DoEvents itself is going to take, does it really matter that it
takes a fraction of a second longer (based on the above numbers)?

Hope this helps
Jay

Lance said:
I've noticed that calling DoEvents is much slower in an application that
has called Application.EnableVisualStyles in Sub Main. Furthermore, the
performance seems to worsen each time that DoEvents is called.
To demonstrate what I'm experiencing, create an app with a Sub Main, a
Main Form, and a Button (called Button1). Include the following code in Sub
Main:
Application.EnableVisualStyles
Application.DoEvents
Application.Run(New MainForm)

Now, include the following code in the Click event handler of Button1:

For i As Integer = 1 to 8000
Application.DoEvents
Next i

On my system the first time that I click Button1 takes ~0.92 seconds.
Subsequent clicks take 1.35, 1.73, 2.12, and 2.52 seconds. But, if I now
remove Application.EnableVisualStyles from Sub Main, then clicking Button1
only takes ~0.07 seconds (and the time does not increase if I continue to
click Button1).
Is this a known issue? Is there a fix? Would it help to enable visual
styles via a manifest file rather than calling EnableVisualStyles?
 
P

Peter Huang

Hi Lance,

Thanks for posting in the community.

First of all, I would like to confirm my understanding of your issue.

From your description, I understand that when you call EnableVisualStyles
and then doevents in a button click event, every time you click the button
the times will increase to call 8000 times doevents.
Have I fully understood you? If there is anything I misunderstood, please
feel free to let me know.

Now I am researching the issue, if I have new information I will update you
with new information ASAP.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

What you said is correct, although I also noticed that it significantly longer to call DoEvents when visual styles are enabled. Thanks for your help.

Lance
 
G

Guest

Thanks for the example!

The reason for my interest is when DoEvents is called from within a long loop in order for an app to respond to the user while the loop is executing. I thought that this technique was faily common. Am I wrong? Is there a better way? If not, then it seems to me that in this case having DoEvents take 13+ times longer can be an issue, depending on the size and structure of the loops.

Thanks again,
Lance
 
T

Trev Hunter

The reason for my interest is when DoEvents is called
from within a long loop in order for an app to respond to
the user while the loop is executing. I thought that
this technique was faily common. Am I wrong? Is there a better way?

It was common in VB6 because there was no supported concept of threads. With
the addition of managed threads to VB.net, the general practice is to spawn
your own thread to do background processing and leave the user interface
thread to respond to user input. This way, DoEvents is not needed.

Here's some links that may help you out with threading:

http://tinyurl.com/383zg
http://tinyurl.com/373zl
http://msdn.microsoft.com/library/en-us/dnadvnet/html/vbnet09272002.asp?frame=true


Be careful of some of the complexities of threading though (e.g. Don't call
a method on a form or control from a different thread without using
Invoke(), be careful when sharing data between threads etc.)

Threading is not recommended for all types of loops though. For example, if
you are populating a listview from an a datatable, don't use a separate
thread to do this - the numerous calls between threads when adding items
will be very slow. Instead I tend to do this by:

1) Spawn a thread to get the datatable from the database - UI won't lock
while this is happening
2) Call back the main thread, pass in the datatable, display a wait cursor
and fill the list (with doevents if a BIG list).

Of course if your background thread is doing processing that doesn't involve
data shared with the form, go ahead and use a thread.

Hth,

Trev.



Lance said:
Thanks for the example!

The reason for my interest is when DoEvents is called from within a long
loop in order for an app to respond to the user while the loop is executing.
I thought that this technique was faily common. Am I wrong? Is there a
better way? If not, then it seems to me that in this case having DoEvents
take 13+ times longer can be an issue, depending on the size and structure
of the loops.
 
J

Jay B. Harlow [MVP - Outlook]

Lance,
I thought that this technique was faily common. Am I wrong?
Its fairly common in VB6. However! you are in VB.NET now! ;-)
Is there a better way?
In VB.NET I would use a Thread or the Application.Idle event to run the long
process. (I would favor a Thread over Application.Idle, mostly becuase a
Thread is easier).

http://msdn.microsoft.com/library/d...onWalkthroughSimpleMultithreadedComponent.asp

Review that entire section of MSDN.

Hope this helps
Jay

Lance said:
Thanks for the example!

The reason for my interest is when DoEvents is called from within a long
loop in order for an app to respond to the user while the loop is executing.
I thought that this technique was faily common. Am I wrong? Is there a
better way? If not, then it seems to me that in this case having DoEvents
take 13+ times longer can be an issue, depending on the size and structure
of the loops.
 
P

Peter Huang

Hi Lance,

Thanks for your quickly reply!

I can reproduce the behavior. Also I have reported it to our product group,
I will get back with more information here ASAP.

Thank you for your understanding.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Wow! BackgroundWorker looks awesome! Now you really have to tell me how to get Whidbey :)
 
P

Peter Huang

Hi Lance,

From the comments of our dev team, I think that the problem is indeed due
to calling the EnableVisualStyles.

In our implementation, each time you call DoEvents, we will place a context
on the activation context stack and also need to acquire a lock for thread
safety, so the operation is a little slower as a result. The reason for the
performance getting worse seems related to more and more contexts you push
on the stack.

Also I don't think it is good practice to call DoEvents a large number of
times, this will cause performance hit, since each call to DoEvents caused
the processing of all pending messages.

Now the workaround is to use a manifest to get visual styles rather than
call EnableVisualStyles.

If you have any concern on this issue, please post here.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top