On Sun, 16 Dec 2007 17:20:27 -0800, Paul E Collins
<fi******************@CL4.orgwrote:
"Peter Duniho" <Np*********@nnowslpianmk.comwrote:
>Mine works fine on my computer with or without the call to Sleep().
I am using Visual Studio 2005 version 8.0.50727.42 with Framework
2.0.50727 on Windows XP 5.1 Build 2600.xpsp_sp2_gdr.070227-2254 : SP2.
Here is a minimal code sample that locks up the UI with an hourglass
and no repainting. If I add a Thread.Sleep(1); in the loop then it
doesn't lock up at all. Is this to be expected? Doesn't it happen for
you?
I guess that depends on what the exact behavior you're seeing is. I
suspect the behavior we're seeing is different, but I can see how
different people might interpret the same behavior differently. So with
that in mind...
First, there are some minor differences in our reported system
configuration. I'm running VS 2005 Pro, .NET 2.0, XP SP2 which is all
basically the same as you. However, my VS version number is actually
8.0.50727.762 (SP.050727-7600), and my OS version is "5.1 (Build
2600.xpsp_sp2_rtm.040803-2158 : Service Pack 2)" (in the System
Configuration utility, it's listed as "5.1.2600.2180
(xpsp_sp2_rtm.040803-2158)" (in the HAL section).
My PC is basically a Core 2 Duo, 2.33Ghz, 2GB of RAM. There's a twist
though, as I'm running XP in a virtual machine, with 768MB of RAM. For
most things though, since the VM is hardware-supported, performance is
identical as compared to running without the VM.
I don't see why those minor differences would have such a significant
effect, but given that there appears to be a difference, maybe they do.
Now, as for what happens when I run the code you posted: I do not find
that the application locks up, nor do I get an hourglass cursor and no
repainting.
You'll note that the code you posted endlessly creates new Bitmap
instances and never releases them, so this obviously eventually results in
an exception (oddly enough, instead of some sort of out-of-memory
exception, I get an "invalid parameter" in the Bitmap constructor...just
another GDI oddity I suppose, trying to tell me that if only I'd asked for
a smaller Bitmap it would've worked :) ). That exception takes about five
minutes to happen on my computer, after about 360000 iterations.
The other thing about the code is that it's in a fairly tight loop. But
every time it calls Invoke() it yields to the main GUI thread. There's no
way for it to starve the loop, but it does have the effect of slowing down
the responsiveness for painting. The Invoke() itself, which requires two
thread switches for each iteration of the loop, is certainly part of the
performance overhead, but I believe the main issue is probably because the
anonymous method instances pile up and eventually have to be garbage
collected, so when the GC steps in everything else has to stop
momentarily. This causes almost a 10X slowdown once the GC kicks in and
starts having to do things regularly (see below for specifics).
So, the fact that this is happening does mean that repainting slows down.
But at least on my computer, it doesn't stop altogether. The application
remains responsive, though occasionally it lags as much as half a second
to a second behind the user actions (dragging the window, obscuring it
with another, etc.)
Because this is timing related, it's possible that if your hardware is
significantly different from mine, that could explain a perceived
difference in responsiveness. But beyond that, the code you posted should
remain responsive on your computer, at least to some extent. If it
literally locks up completely, and you are unable to note _any_ repainting
or other UI response, that would be very odd.
IMHO, the next thing you should do is add a Debug.WriteLine() to the loop,
with a counter printed as part of the debug output. That will help you
differentiate between a true lock-up, in which case you'll only see the
output once (assuming you put it before the call to Invoke()), and just
some sort of sluggish behavior, in which case you'll see the counter
iteratively being printed out.
If the former, then you definitely have some kind of weird problem with
your installation; there's no reason that the code should deadlock, and it
doesn't on my computer.
If the latter, well...the main problem you're apparently running into is
trying to do too much given your configuration (whatever that is). I
don't know how many Bitmaps you're trying to make and add to a list, but I
suppose if it's enough of them you might have problems. But even in that
case, you should see the program _eventually_ respond.
For what it's worth, on my PC, it can run though about 7000 iterations of
the loop per second, at least initially (as the program continues,
iterations take longer because of the memory consumption and garbage
collection overhead, dropping to between 800 and 1000/sec).
Note that for any _reasonable_ number of Bitmaps (say, only a thousand or
so), at least on my computer the operation completes so quickly that any
interruption in responsiveness really isn't relevant. Depending on the
speed of your computer, you may find things work out differently. You
mentioned that batching up the Bitmaps helps performance, so perhaps
that's the solution (assuming you're making a much larger number of them
than I think is reasonable :) ). Most of the overhead in the loop is the
invoking itself, so if you can vastly reduce the number of times you have
to make that thread switch, you can greatly improve performance, returning
responsiveness to the application.
Pete