Disposing of brushes

P

Peter Webb

I am supposed to manually dispose of some instances, such as Brushes, right?

I have a couple of questions:

1. I have the following code, and it works just fine:

penarea.DrawString(selectedslot.drawString,new Font("Arial",fontsize),
new SolidBrush(selectedslot.colour),new Point(0,this.Height/2-(int)
scale)); break;

Just how am I supposed to dispose of the new SolidBrush () ?

2. I create lots of brushes deep down in lots of places, often in loops. How
worried should I be that I am creating brushes but not disposing of them? Is
that some way to enumerate brushes at run time so I can do my own GC when I
know the system is otherwise idle? Can I at least tell in the IDE that I
don't have thousands of brushes being created but not disposed? Or is this
just examining the code?

3. Am I missing something with respect to disposing of things like brushes
and graphics? (Obviously I am, including why they aren't GCed like
everything else). Disposing of them seems a bit of a pain in the arse, but
is seldom discussed on this newsgroup.
 
J

Jon Skeet [C# MVP]

Peter Webb said:
I am supposed to manually dispose of some instances, such as Brushes, right?
Yes.

I have a couple of questions:

1. I have the following code, and it works just fine:

penarea.DrawString(selectedslot.drawString,new Font("Arial",fontsize),
new SolidBrush(selectedslot.colour),new Point(0,this.Height/2-(int)
scale)); break;

Just how am I supposed to dispose of the new SolidBrush () ?

By not creating the brush as a method argument:

using (Font f = new Font("Arial", fontsize))
using (Brush b = new SolidBrush(selectedslot.coulour))
{
penarea.DrawString(selectedslot.drawString, f, b,
new Point(0, this.Height/2-(int)scale)
}
break;
2. I create lots of brushes deep down in lots of places, often in loops. How
worried should I be that I am creating brushes but not disposing of them? Is
that some way to enumerate brushes at run time so I can do my own GC when I
know the system is otherwise idle? Can I at least tell in the IDE that I
don't have thousands of brushes being created but not disposed? Or is this
just examining the code?

You should be worried enough to dispose them yourself.
3. Am I missing something with respect to disposing of things like brushes
and graphics? (Obviously I am, including why they aren't GCed like
everything else). Disposing of them seems a bit of a pain in the arse, but
is seldom discussed on this newsgroup.

They *are* GC'd like everything else - but only at some indeterminate
time, which may be too late. The GC reacts to *memory* pressure, but
brushes, fonts etc take GDI handles - and you could run short of those
without running short of memory.
 
K

KWienhold

I am supposed to manually dispose of some instances, such as Brushes, right?

I have a couple of questions:

1. I have the following code, and it works just fine:

penarea.DrawString(selectedslot.drawString,new Font("Arial",fontsize),
  new SolidBrush(selectedslot.colour),new Point(0,this.Height/2-(int)
scale)); break;

Just how am I supposed to dispose of the new SolidBrush () ?

2. I create lots of brushes deep down in lots of places, often in loops. How
worried should I be that I am creating brushes but not disposing of them? Is
that some way to enumerate brushes at run time so I can do my own GC when I
know the system is otherwise idle? Can I at least tell in the IDE that I
don't have thousands of brushes being created but not disposed? Or is this
just examining the code?

3. Am I missing something with respect to disposing of things like brushes
and graphics? (Obviously I am, including why they aren't GCed like
everything else). Disposing of them seems a bit of a pain in the arse, but
is seldom discussed on this newsgroup.

Classes that implement IDisposable normally use unmanaged resources.
The GC can't deal with those, so they must be cleaned up manually,
that's what Dispose() is for.
If a class does implement IDisposable you should make sure to call its
Dispose method as soon as you are done with it, otherwise you might
leak memory or hold on to resources (Sql-Connections, file handles
etc.) that should have been freed.
There is no automatic way of calling Dispose (unless the class does
this in a finalizer, but you shouldn't rely on that), so every time
you aren't calling Dispose, you are leaking.

In your example, you would normally create an instance of SolidBrush
before the method call and dispose of it afterwards, either by calling
Dispose() manually or with a using-block like so:

using (SolidBrush SelectedSlotBrush = new
SolidBrush(selectedslot.colour))
{
penarea.DrawString(selectedslot.drawString,new
Font("Arial",fontsize),SelectedSlotBrush,new Point(0,this.Height/2-
(int)scale));
}
break;

hth,
Kevin Wienhold
 
P

Peter Webb

Got it. Thanks. They are GCed, but that means the corresponding windows
resources have to wait for the GC, right?

It does seem strange that what appears to me to be an obvious and easily
trapped coding error does not even generate a warning in the IDE. For that
reason I assumed it was reasonable; I will now take this out of my code - I
used it in a few places.

Thanks again
 
J

Jon Skeet [C# MVP]

Peter Webb said:
Got it. Thanks. They are GCed, but that means the corresponding windows
resources have to wait for the GC, right?
Yes.

It does seem strange that what appears to me to be an obvious and easily
trapped coding error does not even generate a warning in the IDE. For that
reason I assumed it was reasonable; I will now take this out of my code - I
used it in a few places.

It's not easily trapped though. What if you pass the resource to
something else which will take ultimate responsibility for cleaning it
up, for instance?
 
C

Christopher Ireland

Peter,
2. I create lots of brushes deep down in lots of places, often in
loops.

You might also like to consider creating one brush and changing its
characteristics (color etc.) for each paint. You then dispose that one brush
after painting. You will find your code will run a lot quicker than
continual creation and disposal of IDisposible objects.

--
Thank you,

Christopher Ireland
http://shunyata-kharg.doesntexist.com

"You can't reason someone out of a position they didn't reason themselves
into."
Author Unknown
 
K

KWienhold

They *are* GC'd like everything else - but only at some indeterminate
time, which may be too late. The GC reacts to *memory* pressure, but
brushes, fonts etc take GDI handles - and you could run short of those
without running short of memory.

I'm somewhat surprised by your response here..
Maybe I'm misunderstanding something, but since when can the GC handle
unmanaged resources, the number one reason to have IDisposable? Maybe
in this special case the finalizer will call Dispose() for you, but
that really should not be generally relied upon, should it?
As far as I understand it, the managed part of the class would
eventually be GC'ed, but any unmanaged resources will leak, though it
is entirely possible that I am missing something.
Could you elaborate please?

Kevin Wienhold
 
J

Jon Skeet [C# MVP]

KWienhold said:
I'm somewhat surprised by your response here..
Maybe I'm misunderstanding something, but since when can the GC handle
unmanaged resources, the number one reason to have IDisposable? Maybe
in this special case the finalizer will call Dispose() for you, but
that really should not be generally relied upon, should it?
As far as I understand it, the managed part of the class would
eventually be GC'ed, but any unmanaged resources will leak, though it
is entirely possible that I am missing something.
Could you elaborate please?

The GC itself doesn't handle unmanaged resources, but anything which
directly owns an unmanaged resource *should* clean it up in the
finalizer. I would consider any class that didn't do so to be buggy -
and given how many people *do* create brushes, fonts etc without
disposing them, I think we'd have heard something if they were actually
leaking :)
 
C

Christopher Ireland

Jon,
I would consider any class that didn't do so to be buggy -
and given how many people *do* create brushes, fonts etc without
disposing them, I think we'd have heard something if they were
actually leaking :)

Maybe that depends on what one considers a leak in a GC context (we've been
here before). I know you know more about this than I do, but I believe that
some people might consider c# code that uses GDI+ IDisposible objects
without explicitly calling Dispose() leaky as this means that the objects
are collected by later GC generations which may give the appearance of a
leak, that is, inflationary memory consumption during the lifetime of the
application.

--
Thank you,

Christopher Ireland
http://shunyata-kharg.doesntexist.com

"To see what is in front of one's nose needs a constant struggle."
George Orwell
 
J

Jon Skeet [C# MVP]

Christopher Ireland said:
Maybe that depends on what one considers a leak in a GC context (we've been
here before). I know you know more about this than I do, but I believe that
some people might consider c# code that uses GDI+ IDisposible objects
without explicitly calling Dispose() leaky as this means that the objects
are collected by later GC generations which may give the appearance of a
leak, that is, inflationary memory consumption during the lifetime of the
application.

I'd consider that a "soft" leak - but if failing to dispose of a Brush
*never ever* released its Windows handle, that would count as a "hard"
leak in my view.

And no, I don't have hard and fast definitions of "soft" leak vs
"hard" leak but I hope they make some kind of sense here :)
 
K

KWienhold

The GC itself doesn't handle unmanaged resources, but anything which
directly owns an unmanaged resource *should* clean it up in the
finalizer. I would consider any class that didn't do so to be buggy -
and given how many people *do* create brushes, fonts etc without
disposing them, I think we'd have heard something if they were actually
leaking :)

--
Jon Skeet - <[email protected]>http://www.pobox.com/~skeet  Blog:http://www.msmvps.com/jon.skeet
World class .NET training in the UK:http://iterativetraining.co.uk- Zitierten Text ausblenden -

- Zitierten Text anzeigen -

Thanks for the clarification, I thought that may be what you meant,
but I wasn't sure.
I agree with you though, if you implement IDisposable you should call
Dispose() in the finalizer and supress the finalizer if Dispose is
called manually.
However, I would not want to rely on other developers actually doing
this. Microsofts code is probably pretty bullet-proof in these
regards, but other third-party libraries may not be. In addition to
that, non-deterministic clean up of unmanaged resources is still
somewhat "leaky", since the finalizer is always called late and may
not even be called at all (even though I am sure you know more about
when this is likely to happen than I do).
So in general I would still strongly suggest you call Dispose yourself
when you are done, but I think there is no argument here.

Kevin Wienhold
 
C

Christopher Ireland

Jon,
I'd consider that a "soft" leak - but if failing to dispose of a Brush
*never ever* released its Windows handle, that would count as a "hard"
leak in my view.

And no, I don't have hard and fast definitions of "soft" leak vs
"hard" leak but I hope they make some kind of sense here :)

I think so. A "soft" leak causes inflationary memory consumption during the
lifetime of the application, whereas a "hard" leak causes an increase in
memory consumption after the application has been closed, relative the the
memory consumption before the application was run.

I think we can agree that in a ideal .NET GC context, "hard" leaks never
occur :)

--
Thank you,

Christopher Ireland
http://shunyata-kharg.doesntexist.com

"If you cannot find the truth right where you are, where else do you expect
to find it?"
Dogen Zenji
 
J

Jon Skeet [C# MVP]

KWienhold said:
Thanks for the clarification, I thought that may be what you meant,
but I wasn't sure.
I agree with you though, if you implement IDisposable you should call
Dispose() in the finalizer and supress the finalizer if Dispose is
called manually.

You only need to do this if you directly hold unmanaged resources
though. For instance, if you hold a FileStream then it's reasonable to
implement IDisposable to forward on the call to Dispose, but not put in
a finalizer - the finalizer of FileStream should take care of it.
However, I would not want to rely on other developers actually doing
this. Microsofts code is probably pretty bullet-proof in these
regards, but other third-party libraries may not be. In addition to
that, non-deterministic clean up of unmanaged resources is still
somewhat "leaky", since the finalizer is always called late and may
not even be called at all (even though I am sure you know more about
when this is likely to happen than I do).
So in general I would still strongly suggest you call Dispose yourself
when you are done, but I think there is no argument here.

Absolutely :)
 
J

Jon Skeet [C# MVP]

Christopher Ireland said:
I think so. A "soft" leak causes inflationary memory consumption during the
lifetime of the application, whereas a "hard" leak causes an increase in
memory consumption after the application has been closed, relative the the
memory consumption before the application was run.

I think we can agree that in a ideal .NET GC context, "hard" leaks never
occur :)

It looks like I haven't actually been clear at all :)

1) I'm talking about GDI handles being leaked, not memory
2) The "soft" leak would mean that GDI handles weren't cleaned up
in a timely fashion, relying on the finalizer. If the finalizer
didn't run in time, you could run out of GDI handles.
3) The "hard" leak would mean that the finalizer wouldn't clean up
GDI handles at all: any time you failed to call Dispse(), you would
end up with a "lost" GDI handle which wouldn't be recovered until
the application closed
4) A leak which still exists after the application has been closed
would count as an OS leak, IMO!
 
K

KWienhold

You only need to do this if you directly hold unmanaged resources
though. For instance, if you hold a FileStream then it's reasonable to
implement IDisposable to forward on the call to Dispose, but not put in
a finalizer - the finalizer of FileStream should take care of it.

Again, that depends on how much you trust the class to do the right
thing ;)
I'd probably still call Dispose on it in my finalizer, if the class
had been designed well odds are that the class would supress its own
finalizer after that, so the overhead should be minimal, if the class
had not been designed well, chances are there wasn't a finalizer in
the first place...
I realize that this is extremly defensive, most of the time your
solution would be cleaner and probably better, especially when you are
dealing with framework classes, but I'm a little paranoid about these
things I guess ;)

Kevin Wienhold
 
C

Christopher Ireland

Jon,
It looks like I haven't actually been clear at all :)

Je je je ..
1) I'm talking about GDI handles being leaked, not memory

Where are GDI handles held?
2) The "soft" leak would mean that GDI handles weren't cleaned up
in a timely fashion, relying on the finalizer. If the finalizer
didn't run in time, you could run out of GDI handles.

My soft leak would be assuming that all finalizers would be run in a timely
fashion (an *ideal* GC environment) but that not explicitly calling Dispose
would mean that they would be called by later generations (gen3, is it?) of
the GC, giving the appearance of a leak, that is, inflationary memory
consumption during application run.
3) The "hard" leak would mean that the finalizer wouldn't clean up
GDI handles at all: any time you failed to call Dispse(), you would
end up with a "lost" GDI handle which wouldn't be recovered until
the application closed

Yes, this is a "hard" leak in my opinion as well. GC simply fails to call
the finalizer in a timely fashion meaning that memory is not released even
after the application has been closed.
4) A leak which still exists after the application has been closed
would count as an OS leak, IMO!

Mmm, IMO, if the GC is responsible for memory allocation during the run of a
..NET application than any memory which hasn't been released after the
application has been closed is responsibility of the GC!

--
Thank you,

Christopher Ireland
http://shunyata-kharg.doesntexist.com

"Why are you unhappy?
Because 99.9 per cent
Of everything you think,
And of everything you do,
Is for yourself -
And there isn't one."
Terence Gray
 
J

Jon Skeet [C# MVP]

KWienhold said:
Again, that depends on how much you trust the class to do the right
thing ;)
I'd probably still call Dispose on it in my finalizer, if the class
had been designed well odds are that the class would supress its own
finalizer after that, so the overhead should be minimal, if the class
had not been designed well, chances are there wasn't a finalizer in
the first place...

I believe the guidelines actually say you shouldn't call any methods on
reference types in finalizers, just in case the instance has already
been finalized.
I realize that this is extremly defensive, most of the time your
solution would be cleaner and probably better, especially when you are
dealing with framework classes, but I'm a little paranoid about these
things I guess ;)

There are pages and pages of guidelines these days. I seem to remember
that Joe Duffy's blog has a pretty recent (2007) set.
 
J

Jon Skeet [C# MVP]

Christopher Ireland said:
Je je je ..


Where are GDI handles held?

I see what you're getting at, but the problem isn't that extra memory
is being taken up: you can run out of handles without running out of
memory.
My soft leak would be assuming that all finalizers would be run in a timely
fashion (an *ideal* GC environment) but that not explicitly calling Dispose
would mean that they would be called by later generations (gen3, is it?) of
the GC, giving the appearance of a leak, that is, inflationary memory
consumption during application run.

Okay, we mostly agree - except that in my view the worse problem is
that you use up handles.
Yes, this is a "hard" leak in my opinion as well. GC simply fails to call
the finalizer in a timely fashion meaning that memory is not released even
after the application has been closed.

After the application has been closed it's up to the OS to clean things
up, not the GC.

But in the scenario I was considering, the GC had called the finalizer
but the finalizer had failed to free the GDI handle.
Mmm, IMO, if the GC is responsible for memory allocation during the run of a
.NET application than any memory which hasn't been released after the
application has been closed is responsibility of the GC!

No - the GC isn't even *running* after the application has been closed.
The GC is part of the application.
 
K

KWienhold

I believe the guidelines actually say you shouldn't call any methods on
reference types in finalizers, just in case the instance has already
been finalized.

Hmm.. That's a valid point of course, so I guess not calling Dispose
on everything in your finalizer is the better solution, since the
chance of actually having a class that holds onto an unmanaged
resource but doesn't have a finalizer are rather slim.
For some reason I never really thought about this, I may just have
some bugs waiting to happen there...
There are pages and pages of guidelines these days. I seem to remember
that Joe Duffy's blog has a pretty recent (2007) set.

Thanks for the pointer, I'll look it up :)

Kevin Wienhold
 
C

Christopher Ireland

Jon,
Okay, we mostly agree - except that in my view the worse problem is
that you use up handles.

It is interesting that you should say that. I hadn't appreciated that there
was a finite set of GDI handles. Would you be so kind as to send me a link
to something I can read about this? It is very relevant to the area in which
I work.
After the application has been closed it's up to the OS to clean
things up, not the GC.

But in the scenario I was considering, the GC had called the finalizer
but the finalizer had failed to free the GDI handle.

Yes, I see. One scenario would be a defect in the finalizer code, and the
other would be a defect in the GC code that calls the finalizer.
No - the GC isn't even *running* after the application has been
closed. The GC is part of the application.

I guess this is the greyest area for me. Say there was a defect in the GC,
either one of the two scenarios described above, in that the GC wasn't
releasing memory. From what I understand of what you've written, you seem to
be suggesting that even in this case it is the responsibility of the OS to
recuperate the memory once the application has closed.

This goes against what I've understood of memory allocation working in
environments which don't have managed memory capabilities. I believe I've
seen cases where applications use up a chunk of memory making it unavailable
to the OS; the memory use after running the application was greater than the
memory use before running the application. In these cases, therefore, it
seemed to me that the OS was not responsible and was even incapable of
recuperating such memory and it was the responsibility of the programmer of
the application to make sure such things didn't happen.

Thank you for helping me deepen my understanding on this subject!

--
Thank you,

Christopher Ireland
http://shunyata-kharg.doesntexist.com

"When I was 10, my pa told me never to talk to strangers. We haven't spoken
since."
Steven Wright
 

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