C# and GDI Resources

I

Ian Semmel

In MFC programming, you have to carefully check usage of GDI resources (eg
dispose of them when no longer needed).

Does the same apply to C# and .NET ?

eg if I have

Font f = new Font ();

..... use it

f = new Font ();

Do I have to put f.Dispose() in prior to the second new or does GC work it out
for you ?
 
G

Guest

Yes, you should call Dispose() on any disposable object once you are finished
using it. By a 'disposable' object, I mean something which either implements
IDisposable or has a method with equivalent semantics; such as Close(). It
is true that the GC will dispose of such resources, but there are no
guarantees as to when or even if that will happen.

Don't forget that if you are creating and disposing of an IDisposable object
in the same lexical block, you can use C#'s using statement to ensure that
the object is disposed of regardless of whether an exception is thrown. Such
as:

using( Foo bar = new Foo() )
{
bar.DoStuff();
} // bar.Dispose() is called here.

Josh
 
J

John B

Ian said:
In MFC programming, you have to carefully check usage of GDI resources
(eg dispose of them when no longer needed).

Does the same apply to C# and .NET ?

eg if I have

Font f = new Font ();

.... use it

f = new Font ();

Do I have to put f.Dispose() in prior to the second new or does GC work
it out for you ?

Yes, you should explicitly dispose of any IDisposable objects (or wrap
in a using statement).

JB
 
D

_DD

Yes, you should call Dispose() on any disposable object once you are finished
using it

I'm curious about this. What happens if you don't call dispose...what
are the usual symptoms?

Also, is there any way to set a 'marker' when a suspicious program
runs so that resources can be reclaimed afterward?
 
A

Andy

Memory leaks, dabatbase connections which hang open until they
timeout..

It can be pretty nasty actually. Be very careful to dispose any object
implementing IDisposable. In practice, even classes which have a Close
method implement this interface (and indeed, close just usually calls
dispose).

Andy
 
I

Ian Semmel

John said:
Yes, you should explicitly dispose of any IDisposable objects (or wrap
in a using statement).

JB

But suppose I have a function say

void fn ( Font f )
{
if ( condition )
{
f.Dispose ();
f = new Font ();
}
....
}

How do I know that f is not being used somewhere else ?
 
A

Andy

The object that creates the instance is the one that must dispose of
it, usually. So you wouldn't dispose of any parameters which are
passed in; that would be the callers responsibility.
 
D

_DD

Memory leaks, dabatbase connections which hang open until they
timeout..

It can be pretty nasty actually. Be very careful to dispose any object
implementing IDisposable. In practice, even classes which have a Close
method implement this interface (and indeed, close just usually calls
dispose).

Andy, Thanks for your reply. I was particularly interested in regard
to graphics resources. All programs (incl old Win32) can allocate
them, and it seems there are lots of places for things to go wrong. I
guess my primary questions would be:

When graphics resources run out, what are the usual symptoms shown at
operating system level?

Can anything be done to correct this after it happens, short of a
reboot?
 
I

Ian Semmel

That's interesting. I was working on the assumption that in C# and .NET that
anything goes, but it appears that not everything is so straight forward.

The trouble with C# is that it is so high a level, that it is not always clear
what is going on behind the scenes (cf MFC where you are working directly with
the dlls).

It could be that over time, there will be a lot of pretty wild and wooly .NET
programs out there.
 
A

Andy

DD,

Likely memory leaks, but there may be other symptoms as well, although
I don't know what they might be off-hand.

A reboot would certainly 'fix' the problem. I'm not sure how else the
system would know to reclaim the memory. I'm going to reply to the
next person in this thread; that may have more info for you.

Andy
 
A

Andy

Nope, not anything goes. Like all programming, there are rules and
gotchas.

I'm pretty sure that all objects which implement the IDisposable
interface use unmanaged resources; i.e. they end up being a wrapper to
a COM DLL call, which .Net cannot know what other programs are using
that particular COM object server. So .Net can't free unmanaged
resources automatically, because other applications may actually be
using those same resources.

The rule is, if the object has a Dispose or Close method, make SURE you
call it when you are done with it. If you're using anything from
System.IO, System.Windows.Forms, and System.Data.* you'll defaintly
come across such classes. There are others throughout the framework as
well.

As long as you follow that rule, you'll be fine. As an example, if
your class opens a database connection when an object is instanciated
from that class and keeps the connection around the entire lifetime of
your object, you should implement IDisposable as well. Your dispose
method would make sure to Dispose the database connection. Its up to
the client of your object to call Dispose on your object.

I think that if you don't call Dispose, eventually it will be called
when the garbage collector finalizes the objects, but that is a HUGE
performance hit, and in the case of a database connection, you keep a
connection open much longer than you really need to. So you shouldn't
rely on the finalizer.

I had a bug in my custom Data access layer used by my application where
my SqlDataReaders weren't being disposed after I was done using them.
What ended up happening was that each instance of my application
started using about 10 - 20 different connections to the Sql server, to
the point where the server wasn't responding as well and data
operations started getting exceptions when it tried to open a new
connection. This happened pretty quickly because even though I had a
few users, every 30 seconds the app would hit the database. The bug
was in my data layers Find code; I wasn't disposing the DataReader when
I was done. I just put the data reader into a using( ) {} block,
recompiled and distributed the new application.. now the app uses one
connection (via connection pooling) to do its work, there are no more
errors and the server is very responsive again. The moral is to always
make sure to dispose your disposable objects, using the using block (in
C#, VB has an equivelent).

HTH
Andy
 

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