Disposal of GDI Resources and GDI Limits, a puzzling question (for meat least)

C

Chris Dunaway

When working with GDI+, calling the CreateGraphics method to draw on a
control has normally been frowned upon and it is always emphasized to
dispose of pens and brushes and other GDI objects lest you run out.

But consider the following code (in a timer elapsed event on a Windows
Form):

private void TimerFunc(object sender, System.Timers.ElapsedEventArgs
e) {
Graphics gdi = this.CreateGraphics();

int x, y;
int w, h;
int r, g, b;

x = _random.Next(0, this.ClientRectangle.Width + 1);
y = _random.Next(0, this.ClientRectangle.Height + 1);
w = _random.Next(5, 250);
h = _random.Next(5, 250);
r = _random.Next(0, 256);
g = _random.Next(0, 256);
b = _random.Next(0, 256);

Pen p = new Pen(Color.FromArgb(255, r, g, b));

gdi.DrawEllipse(p, x, y, w, h);
}

Note that I am calling CreateGraphics and creating a new Pen without
disposing of either. This method handles a Timer Elapsed event. I
set the interval of the timer to 50ms. So basically, i draw random
ellipses on the form.

But when I montior the app in Task Manager, Process explorer, or a GDI
monitor, the number of GDI objects does not change. They do not go
up, even if I let the code run for minutes at a time. I even added
the following loop in the elapsed event:

List<Pen> penList = new List<Pen>(50000)
for (int i = 0;i <= 50000;i++) {
penList.Add(new Pen(Color.FromArgb(255, r, g, b));
}

Even after creating 50000 new Pens, the GDI object count did not
change! Memory usage increased (Working Set size) slightly but not in
significant amounts for the duration of this test.

Can anyone explain this behavior? I expected to see the GDI object
count increase since I did not dispose of any of the objects. My
understanding was that the gc only triggered on memory pressure and
not handle pressure.

Why bother disposing of pens and brushes and the like if it doesn't
seem to have an effect on the GDI handle count? Have I missed
something obvious?

Thanks for any insight!

Chris
 
C

Chris Dunaway

When working with GDI+, calling the CreateGraphics method to draw on a
control has normally been frowned upon and it is always emphasized to
dispose of pens and brushes and other GDI objects lest you run out.

But consider the following code (in a timer elapsed event on a Windows
Form):

private void TimerFunc(object sender, System.Timers.ElapsedEventArgs
e) {
Graphics gdi = this.CreateGraphics();

int x, y;
int w, h;
int r, g, b;

x = _random.Next(0, this.ClientRectangle.Width + 1);
y = _random.Next(0, this.ClientRectangle.Height + 1);
w = _random.Next(5, 250);
h = _random.Next(5, 250);
r = _random.Next(0, 256);
g = _random.Next(0, 256);
b = _random.Next(0, 256);

Pen p = new Pen(Color.FromArgb(255, r, g, b));

gdi.DrawEllipse(p, x, y, w, h);

}

Note that I am calling CreateGraphics and creating a new Pen without
disposing of either. This method handles a Timer Elapsed event. I
set the interval of the timer to 50ms. So basically, i draw random
ellipses on the form.

But when I montior the app in Task Manager, Process explorer, or a GDI
monitor, the number of GDI objects does not change. They do not go
up, even if I let the code run for minutes at a time. I even added
the following loop in the elapsed event:

List<Pen> penList = new List<Pen>(50000)
for (int i = 0;i <= 50000;i++) {
penList.Add(new Pen(Color.FromArgb(255, r, g, b));

}

Even after creating 50000 new Pens, the GDI object count did not
change! Memory usage increased (Working Set size) slightly but not in
significant amounts for the duration of this test.

Can anyone explain this behavior? I expected to see the GDI object
count increase since I did not dispose of any of the objects. My
understanding was that the gc only triggered on memory pressure and
not handle pressure.

Why bother disposing of pens and brushes and the like if it doesn't
seem to have an effect on the GDI handle count? Have I missed
something obvious?

Thanks for any insight!

Chris

BTW: I'm using VS2005 and c# for this test.
 
B

Bob Powell [MVP]

GDI+ resources have little or nothing whatsoever to do with GDI resources.

Correctly calling Dispose _can be_ important because the GDI+ dll is
unmanaged and therefore the wrapper classes used by .Net needs to cope
with unmanaged resources. The garbage collector will dispose of these
GDI+ resources eventually but proactively managing them can be useful
when performance is important.

See the #1 most-asked question, yes, even after seven years of posting
it's still #1, for why and how of CreateGrphics.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
 
C

Chris Dunaway

GDI+ resources have little or nothing whatsoever to do with GDI resources.

I thought that things like the Graphics object or a Pen were just
classes wrapped around an OS handle of some kind, like a device
context. Is that not so?
Correctly calling Dispose _can be_ important because the GDI+ dll is
unmanaged and therefore the wrapper classes used by .Net needs to cope

Do you think the sample code I provided will cause problems in the
long run? I would never write code like this, but I was just puzzled
that it didn't seem to cause any problems.

Chris
 

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