Diposer for GDI+ resources (Pen, Brush, ...)

Introduction

The draw resource classes found inside the System.Drawing namespace (Pen, SolidBrush, ...) are actually wrapping the underling native Windows GDI resources. Like all system resources, their amount is limited, and so they should be returned to the Operating System as soon as possible.

That's why .NET documentation tells you to call the Dispose() method on Pens, Brushes etc., as soon as they are not used anymore.

Background

But .NET is a managed environment and has a garbage collector, then why do we have to manually release resources? Consider the following usual paint code:

Pen and SolidBrush are internally holding unmanaged native Win32 GDI resources (HBRUSH, HPEN etc.). These are precious Windows system resources and should be released as soon as possible. When OnPaint() exits, the only references to myPenX and myBrushX are gone, so the .NET garbage collector will release the instances sometime later. This will, of course, also release the underlying native handles. But the point is, sometime later. For the time span between the last reference gone and the garbage collector releasing the unused instances, the underlying native resources are occupied although not in use anymore. This can be a problem on heavy system load situations. And, like all resources, we should use them not more than necessary, and return them as soon as we do not need them anymore.

If you have a complicated drawing routine incorporating many pens and brushes, calling Dispose() on all instances can be a tedious and error prone task. You easily add a new brush in the middle of your code and forget to call Dispose() on it before method exit. And be aware: if an exception is thrown somewhere in your drawing code, the control flow can jump out of OnPaint() without running to its end. So, the Dispose() of your instances will not be called at all.

C# provides the using statement for this situation:

protectedoverridevoid OnPaint(PaintEventArgs e)
{
using (Pen myPen1 = new Pen(Color.Black, 3))
using (Pen myPen2 = new Pen(Color.Lime, 3))
using (SolidBrush myBrush1 = new SolidBrush(Color.Red))
using (SolidBrush myBrush2 = new SolidBrush(Color.Lime))
{
// use myPenX and myBrushX for drawing
}
// here all resources created inside using() are diposed,
// also in case of an exception or return statement
}

This solves the problem perfectly for simple OnPaint() methods. But if there is more complicated painting involving different paint resources depending on the control's state, we have to create all possibly used resources before painting:

protectedoverridevoid OnPaint(PaintEventArgs e)
{
using (Pen myPen1 = new Pen(Color.Black, 3))
using (Pen myPen2 = new Pen(Color.Lime, 3))
using (SolidBrush myBrush1 = new SolidBrush(Color.Red))
using (SolidBrush myBrush2 = new SolidBrush(Color.Lime))
{
if ( some condition )
{
// use myPen, myBrush1 and myBrush2, myPen2 is not used
if ( some other condition )
{
// use myPen2
}
}
else
{
// use myPen1 and myBrush1 for drawing,
// myPen2 and myBrush2 are never used
}
}
// here all resources created inside using()// are diposed, also in case of an exception or return
}

Of course, this is not a big deal if only one brush or pen is unnecessarily created. I do visualizations for industrial processes, and there we use sophisticated user controls involving a lot of complicated painting using many different resources. And, there are two big 1600x1080 screens showing many of those controls on the same time. All the needless draw resources created have a measurable impact on the system performance. To avoid this, we would end with something like this:

So far, so good. But imagine the code we are ending up with if there are 6 conditions and 12 draw resources, some of them used in all control paths, some in only one, some in three of them, and so on. The resulting construct of nested using statements is hard to read and even harder to maintain. If the drawing code changes and a resource used before only in one control path is newly used in another control path too, we have to rearrange the whole code.

Helper class to dispose drawing resources on method exit

I have a strong C++ background, and in C++, it is a best practice to encapsulate resources in objects to get them released as soon as they go out of scope. This is especially important to make code exception safe. So, I ported the C++ approach to C#: have a helper class releasing resources.

All drawing resource classes in the System.Drawing namespace implement the IDisposable interface. It declares a method, Dispose(). For details, see the MSDN documentation on IDisposable. We add all object instances to be disposed to an instance of Disposer, which iterates the internal list and calls Dispose() on all entries. Be aware that this code is not thread safe. For this, m_disposableList and m_bDisposed would need to be protected with a lock(). The intended use case for this helper class is inside user controls, where all members have to be accessed from the thread which initially created the control anyway.

Usage of the Disposer helper class

Now, the OnPaint() method is changed to use the Disposer helper class:

Just add every instantiated drawing object to the Disposer, drawResDisposer, and on exit of the code block surrounded by using {}, drawResDisposer.Dispose() is called automagically, which calls the Dispose() of all the instances added to it. No need to know which of the draw resources where actually needed and created. Just add them to the disposer, use them, and forget about them. I think this is a much cleaner and easier to maintain code structure.

The Disposer class can also be used for every other class encapsulating native and unmanaged resources. As long as the class implements the IDisposable interface.

I am a fan of one single kind of programmer laziness only: Don't do things manually which can be done by the compiler or the runtime automatically.

Improving the Disposer with WeakReference

In advanced user controls, we should not create all drawing resources on each call of OnPaint(). Painting occurs quite frequently in situations like resizing. It is a waste of resources to create a pen every time it is used and then hand it over to the garbage collector for destruction directly. Each drawing resource should be created on first use, and disposed inside the control's Dispose() method. In other words, we create a singleton for each different drawing resource type used for painting. This way, the resources are held by the control during its lifetime, but this is still better than constructing and destroying the same drawing resources over and over again. But, this approach makes the problem even worse: the resources are now created and destroyed in different methods of the control class, so it is much harder to get the Dispose() of each resource called inside the control's Dispose() method. If we fail to dispose the disposer instance when the control gets destroyed, the internally existing references to the IDisposable instances stop the garbage collector from freeing them. Less than better...

To make the disposer helper class more useful in such situations, it is changed to use the .NET System.WeakReference class. It allows the garbage collector to free an object although there is still a reference, a weak one. See the MSDN documentation for details. This class is made for such kind of situations: a reference to an object which can be used to dispose it but does not count itself as a reference for the garbage collector.

All you have to is add the lines shown in bold. If you forget the call to m_Disposer.Dispose(), the garbage collector will take care of the draw resources. The references held inside the disposer class do not count for the garbage collector anymore. This is exactly what we want.

Points of interest

If the code block following using() is left on any path, including an exception, a return in the middle etc., myVar.Dispose() is called implicitly. The needed calls are inserted by the C# compiler. The only restriction for types used in using() is that they implement IDisposable.

The using statement is actually just syntactic sugar which is extended by the C# compiler to the following code. You can see this if you inspect your binary assembly with Reflector:

Conclusion

Although no resources will really be leaked by not calling Dispose() on GDI wrapper classes, it's a good habit to do so. This way, they are released when they are not needed anymore, and not sometime later when the garbage collector is run the next time.

Better idea?

I'm aware of the fact that this is a C++ approach. I'm relatively new to C#, but did C and C++ since more than a decade before. So, if you have a more "C#-ish" way to do this, please tell me.

History

07/07/2009 - Initial version.

10/13/2009 - WeakReference version added, some minor text additions.

10/22/2009 - Reworked code samples to better show the intended use case.

In my opinion, the article clearly states the problems with plain using {}.

If you ever write a complicated user control with a lot of control state depending paint code you will discover what I mean.You will also see the performance impact of creating the same paint resources over and over on each call of OnPaint() if you have a big 1600 x 1050 screen showing >50 of your user controls at the same time. Especially if your PC has other things to do in the background than garbage collecting thousands of paint resources per second. Just try it out.

Hence, the article really should use different examples, say Fonts and pens with a width larger than 1.

Or better yet, code which may (depending upon what's being drawn) either use a stock object or a newly-created one. Which is nicer (bearing in mind that one Disposer object can handle many brush, font, pen, and other objects:

Using Dispos as New Disposer
Dim BR1 as Brush,BR2 as Brush
If Color1=Color.Black then
BR1 = Brushes.Black
Else
BR1 = New SolidBrush(Color1)
Dispos.Add(BR1)
End If
If Color2=Color.Black then
BR2 = Brushes.Black
Else
BR2 = New SolidBrush(Color2)
Dispos.Add(BR2)
End If
.. Now do stuff with BR1 and BR2
End Using

or, if not using Disposer:

Dim DisposBR1 = False
Dim DisposBR2 = False
Try
If Color1=Color.Black then
BR1 = Brushes.Black
Else
BR1 = New SolidBrush(Color1)
DisposBR1 = True
End If
If Color2=Color.Black then
BR2 = Brushes.Black
Else
BR2 = New SolidBrush(Color2)
DisposBR2 = True
End If
.. Now do stuff with BR1 and BR2
Finally
If DisposBR1 Then BR1.Dispose
If DisposBR2 Then BR2.Dispose
End Try

I would think approach #1 would be far less error-prone, though it might be improved by adding a generic function to Disposer which would add its argument and return it (allowing something like:

Suppose you're writing a paint routine for an object which will often use pre-existing graphic objects, but which may need to create temporary ones. Wrapping the routine with a "Using xxx as Disposer" clause and then adding to the Disposer any temporary objects which are created, seems cleaner than any other approach I can think of. What approach would you suggest, given that it's not possible to execute code inside a "Using" block without creating an object before the code starts and disposing the object after the code ends?

When each temporary object is created, the code that creates it will know that the lifetime of the object will be temporary. Placing all of the code for object disposition at the point of object creation seems much safer than requiring cleanup code to know which objects are temporary and which are persistent.

I would seriously question the authors of these books regarding any implied or stated concepts related to cache of GDI objects.Any performance improvements (would probably be miniscule) would evaporate when System Resources are not released and become scarce.I have seen this happen many times.For a graphic example a small change in the code resulted in large CPU utilisation improvements and I am not even sure why.http://www.codeproject.com/Messages/3181845/Tidy-up-the-code-equalsequals-Fix-CPU-utilisation.aspx

I can't see any reason, why I should use something like a "Disposer": Neither it saves lines of code, nor it guaranties, that all resources will be released (instead of calling obj.Dispose() I must call xxxDisposer.Add(obj))...So what's the advantage of the Disposer??

I like it better, because I can call xxxDisposer.Add() directly after creating every GDI object to dispose and then forget about it.If I have to call obj.Dispose() for each single object, it's somewhere else in the code.I did some complicated user controls with lot of conditional draw code in OnPaint() and subroutines inside OnPaint() which is only executed in certain states of the control. Of course the GDI objcets shall also created only if needed. I like it better than have using {} or obj.Dispose() all over my code. Especially when refactoring. And I find it much easier to get it exception safe.

If course it's not "better" or faster, but in my eyes this approach results in a much cleaner code structure. It's syntactic sugar.If your OnPaint() method has 10 lines of codes and uses 3 draw objects, it's of course not worth the effort.

Suppose you may wish to create foreBrush in one of two ways, and the code that uses it will be the same regardless of how it's created. The only ways I can see to accomplish that with 'using' would be to either write a separate function to perform the object creation one of two ways (and call that function from the object-creation part of the 'using' statement) or else to move all the code that acts upon the object to a separate function which is called by separate 'using' statements. In many circumstances, the latter approach will be downright disgusting; the former approach might not be too evil, but it won't always work.

For example, suppose you want to draw something using either a default font (which is kept in a control's class field) or a named font. If one is using a named font, one must create it and then dispose it. If one is using the default object, one must not dispose it. It would seem the disposer class would make things easy:

This approach could be used with Managed Direct X. If you want to ensure that objects are disposed in the right order, or at all. Instead of using a list with direct referene to the objects, you should look at a list of WeakReference's:

List<WeakReference> myGarbage = new List<WeakReference>();

Before calling dispose you should test if the object is collected using the IsAlive property.

Yes, using WeakReference would work too. But I cant see any advantage of doing so.If the disposer class is used as described in the article, Dispose() of all contained references is called at the same point as if it would be when called manually. But in an exception save way and with a (in my opinion) more readable code structure. Compared to wrapping each GDI object with it's own using {} statement.The purpose of WeakReference is to allow the GC to trash an object altough someone is still knowing it. This situation cant happen here.

Another point is WeakReference would brake strict compile time type safety. Yes, I know, it's kind of a fetish for a longtime C++ programmer We would have to write something like:

So no need for another class to track these objects, no need to remember to add them to that object and if during code reviews you see a Pen, Brush, Bitmap, ... being created and it isn't in a using() statement and there isn't a comment there to explain why it's needed outside the current scope then you can discuss with the author and get a using() or comment added as appropriate.

Yes, for trivial painting routines that's of course true.I created the class described inside the article while developing some complicated user controls with large OnPaint() methods.There you often have parts painted only in certain states of the control. So the paint resources shall also be allocated only if needed.

Usage of using() for each individual GDI resource wrapper would lead to the following code structure:

There you often have parts painted only in certain states of the control. So the paint resources shall also be allocated only if needed.

I wouldn't consider the above code structure to be objectionable. As a better example, you should consider a control that e.g. has to do a lot of stuff with what may be either a persistent object or a specially-created one. In the latter situation, the object must be disposed, while in the former it must not. While one could manually use a flag to keep track of whether the object needs to be disposed and take care of it in a 'finally' block if so, I would think the Disposer object makes things much cleaner and less prone to mistakes.