Click here to Skip to main content
6,295,667 members and growing! (15,643 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » .NET Framework » General     Intermediate

GC 102

By Ernst Kuschke

Further notes on programming for the Garbage Collector.
C#, Windows, .NET 1.0, .NET 1.1, Visual Studio, Dev
Posted:2 Mar 2004
Views:38,832
Bookmarked:22 times
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
14 votes for this article.
Popularity: 4.65 Rating: 4.06 out of 5

1
1 vote, 7.1%
2
1 vote, 7.1%
3
7 votes, 50.0%
4
5 votes, 35.7%
5

Introduction

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.

Cool C# feature: using

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.

Cool C# feature: foreach

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

Performance issues

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:

  1. Enlisting in the Finalization queue
  2. Removing from Finalization queue to be enlisted in To Be Finalized queue
  3. Calling Finalize on the component
  4. Removing from To Be Finalized queue

It should be obvious that, if possible, the shortcut should be taken, and Finalizable components avoided. To do so, and this is quite important:

  1. Don�t create Finalizers (or destructors) for your components unless absolutely necessary.
  2. For components where you do need a destructor, always call 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.

Threading

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).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Ernst Kuschke


Member
Ernst develops software for the agricultural industry.
He moderates the SADeveloper INETA community, and gives talks on development-related stuff from time to time.
He is an MVP in Visual C#, but whilst he advocates the adoption of .NET, he is also skilled in non-Microsoft technologies.
Sometimes he chats about it.
Occupation: Web Developer
Location: South Africa South Africa

Other popular .NET Framework articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 5 of 5 (Total in Forum: 5) (Refresh)FirstPrevNext
GeneralIncorrect code example PinmemberStaffan O22:34 9 Mar '04  
GeneralRe: Incorrect code example PinmemberErnst Kuschke20:55 10 Mar '04  
GeneralRe: Incorrect code example PinmemberdzCepheus20:40 14 Mar '04  
Generalforeach does not call Dispose on collection, but on enumerator PinmemberFrank Hileman4:28 9 Mar '04  
GeneralRe: foreach does not call Dispose on collection, but on enumerator PinmemberErnst Kuschke9:29 21 Apr '04  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin 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