![]() |
Platforms, Frameworks & Libraries »
.NET Framework »
General
Intermediate
GC 102By Ernst KuschkeFurther notes on programming for the Garbage Collector. |
C#, Windows, .NET 1.0, .NET 1.1, Visual Studio, Dev
|
|
Advanced Search |
|
|
|
||||||||||||||||
In GC 101, I discussed the reasons for Finalize and Dispose, and how to implement these methods in your components. The C# language has some nice built-in functionality to help you with the Disposing pattern, which I will discuss here.
Consider the following code:
SqlConnection cn = new SqlConnection(cnString);
cn.Open();
//Use the open connection
cn.Dispose();
If an exception had to be thrown on the call to Open, Dispose will never get called, and your resource might leak. I'm sure you already know the solution:
try
{
SqlConnection cn = new SqlConnection(cnString);
cn.Open();
//Use the open connection
}
finally
{
cn.Dispose();
}
This code does exactly what the first listing does, but is safer - you are guaranteed that Dispose will be called. But, it is also much less readable! C# has a nice feature to help with readability here: the using clause. Our code can be rewritten as:
using (SqlConnection cn = new SqlConnection(cnString))
{
cn.Open();
//Use the open connection
}
Lovely, isn�t it? As soon as the using block exits, Dispose will automatically be called on all objects that implement IDisposable and are created with the using-clause. If you look at the compiler-generated IL, you will see that a try - finally is actually implemented.
You might have collections of expensive (disposable) objects from time to time. To ease coding against your collection, have it implement IDisposable:
internal class openDBConnectionsEnumerator : IEnumerator, IDisposable
{}
public class openDBConnections : IEnumerable
{
public IEnumerator GetEnumerator()
{
return new openDBConnectionsEnumerator();
}
}
Now, you can use your collection in a foreach loop, and Dispose is called automatically on your collection when the loop exits:
OpenDBConnections cons = new OpenDBConnections();
foreach(DBConnection in cons)
{
//Do something with connection object
} //Dispose is called on the IEnumerator when loop exits
The GC has only one thread that calls Finalize on all the objects in the finalization queue, and thus might have a tough time in keeping up with Finalizable objects created by more than one user thread. A shortened overview of a Finalizable object�s lifespan:

There are actions here that impacts negatively on performance:
Finalize on the component
It should be obvious that, if possible, the shortcut should be taken, and Finalizable components avoided. To do so, and this is quite important:
Dispose on your component when appropriate. This suppresses the GC's call to Finalize and saves you the overhead of calling Finalize and enlisting in the To Be Finalized queue. A component�s Dispose(bool) method should never be called from both the GC�s finalizer thread and a user thread. There may be instances where more than one user thread calls the method. In this case, make your cleanup code thread safe in exactly the same way you�d make any code thread safe. If you are 100% sure that your code will not be called by more than one user thread at a time, don�t enforce thread-safety, as this impacts negatively on performance.
(You will also find this article on my blog).
| You must Sign In to use this message board. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 2 Mar 2004 Editor: Smitha Vijayan |
Copyright 2004 by Ernst Kuschke Everything else Copyright © CodeProject, 1999-2009 Web15 | Advertise on the Code Project |