views:

197

answers:

6

Is it necessary to manually manage the lifetime of System.Drawing objects?

Currently I am employing 'using' statements to minimise the lifespan of Brushes and other Drawing objects e.g.

using ( Brush br = new SolidBrush( color ) )
{
    // Do something with br
}

Is this necessary or is it safe to let the garbage collector work its magic when and if it needs to?

As a quick aside to the question... what do people think is the cleanest way to achieve this?

+2  A: 

The general rule of thumb is that if an object implements IDisposable you need to clean it up. IDisposable is not implemented on a whim in the .NET Framework - There are good reasons for it to be there.

Colin Mackay
+8  A: 

When an object is IDisposable, then it is better to dispose it as soon as you do not need it any more. (It implements IDisposable for a reason).

Offcourse, when you forget to call Dispose, the Garbage collector will do its work at some time, and clean it up, so that resources are freed, but you can never tell or guess when the Garbage Collector will kick in, it is not deterministic.

So, my advice is: call Dispose manually (like you're doing now) as soon as you do not need the disposable object any more.

Frederik Gheysels
+1  A: 

As the others said: when you create an IDisposable object, you should Dispose it as soon as possible. In your specific example, if the color is known at compile time, you could use a standard brush such as Brush br = Brushes.Blue which you don't need to dispose.

Henrik
+1  A: 

If you are re-using the same colour over and over you could store the brush as a class-level member, however this would mean that the owning class should be IDisposable too, and dispose the brush member in it's dispose method. This would increase the memory storage (by the size of one brush), but might reduce the amount of code (no using statements but an additional Dispose override).

Dr Herbie
I like this idea, unfortunatly, I have made the decision to abstract away all this Drawing functionality into a support type class. As such there is no 'owner' of the support functions, meaning that final disposal ould still be an issue. Coupled with the fact that these functions could be accessed from multiple threads means that adding class level variables could end up being more troubl then its worth!
TK
A: 

I am using the 'using' statement just as you described in your question to guarantee that the Brush, Pen, Font, whatever resource is disposed of properly. In my code, I find the using statements cleaner than having explicit .Dispose() calls scattered throughout. But that's just my preference.

I agree with the answers above though: regardless of whether you prefer using statements or .Dispose calls, it's pretty important to clean up the resources manually, rather than relying on the garbage collector. (I was relying on the garbage collector at first and performance problems began to surface, even before things in the app were getting complicated.)

+1  A: 

It is good to Dispose of System.Drawing object, however if you miss one or two when you get an exception etc, it is not the end of the world. (Other objects like opened files and database connections must always be disposed)

Having lots of “Using” statement all over your code make it more complex to understand. I would therefore in the case of System.Drawing object, consider just calling Dispose() on them at the end of the method.

In the past I have used a class I written “Dustcart”, that implements IDisposable, and contains a collection of objects to dispose. You can then write code like:

using(var dustcart = new Dustcard())
{
   var p = dustcart.Add(new Pen(red, etc));
   var b = dustcart.Add(new Brush(black));

   Pen t;
   if (someFlag)
   {
      t = p;
   }
   else
   {
      t = dustcard.Add(new Pen(etc));
   }
}
Ian Ringrose
I like the idea that by disposing of the dustcart you can dispose of all the items in it! I think this is definatly something that Im going to try and remember the next time I need to consider managing the lifespan of an object. However, I imagine that this would only be benificial when you see lots of nested using statements or multiple objects that need disposal.
TK
@Tk, it is most useful when you conditionally create new objects or reuse existing object, e.g. when simple "nested using statements" are not enough. In simple cases "using" is best, as everyone knows what it means
Ian Ringrose