Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I create new Pens/Brushes per Paint request or keep them throughout the application lifecycle?

I have an application that does a lot of drawing, let's pretend it's a Viso-like application. It has objects that have multiple sub-objects that are drawn, things can be connected, resized etc. Currently when I call paint on a particular sub-object or object, I do the following:

using(var pen = new Pen(this.ForeColor))
{
    // Paint for this object.
}

I've read conflicting answers that this should be done for an application that is constantly drawing the same thing (maybe just resized, moved etc). Should I store the Pen/Brush with the object and then dispose them all when the application is disposed of, or are they efficient enough to be created/disposed for each paint call (remembering that this is a pretty graphics intense application).

EDIT: There are already two answers that have conflicting answers and this is where I'm not sure to make the switch. Does anyone have any stats on the differences?

like image 358
TheCloudlessSky Avatar asked Aug 20 '10 16:08

TheCloudlessSky


2 Answers

You could of course use the Pens and Brushes classes that provide you with objects that are already created by the runtime.

For example, if you want one of the standard colour Pens, you can do this:

var pen = Pens.Red;

Likewise you can do the same with Brushes, if you just want standard solid brush colours:

var brush = Brushes.Red

Using these, you don't need to worry about cleaning them up, disposing it or otherwise.

If you want different colours that you create yourself, for example with a different alpha component, or a gradient brush perhaps, then you still need to create these yourself and clean them up appropriately.

EDIT:

To create and dispose of an array of 100,000 new pens took approximately half a second on my ancient old XP machine, running a test app in Debug mode.

That equates to approximately 5 microseconds per pen. Only you can decide if that is fast enough for you. I would hazard a guess that this time may be largely insignificant with regard to the rest of your operations.

like image 196
Andy Avatar answered Sep 21 '22 19:09

Andy


You'll only know the performance impact by testing on your particular application, but the framework doesn't seem to have a problem keeping a few pens around for the life of the application. The first time you call Pens.Black, it creates a black pen and caches it. You get the same object back for future calls, and it's never explicitly disposed (Pens.Black.Dispose() will actually throw an exception). However, you don't want to blindly create pens and leave them to be disposed when the application ends, because you'll be leaking unmanaged memory. A couple of options spring to mind depending on the pattern of usage in your app.

Give each object a private Pen that's created when ForeColor is set and reused for all painting. You should make your object IDisposable so that it can dispose of that Pen properly.

If you're using relatively few distinct colours but lots of objects use each colour, you may not want each object to hold on to its own Pen. Create some cache class that keeps a Dictionary<Color,Pen> and hands them out through a PenCache.GetPen(ForeColor). Like using Pens.Black, you can now forget about disposing them. A problem arises if you use a colour briefly, then don't need it again. The Pen got cached, so you're stuck with it in memory forever. You could keep a Dictionary<Color,WeakReference<Pen>> instead, allowing cached pens to be eventually garbage collected if they're no longer needed.

That last option may be the best general purpose solution, avoiding gratuitous creation and disposal while letting the garbage collector make sure that orphaned pens don't cause too much memory trouble. It may, of course, not be any better in your particular case.

like image 38
stevemegson Avatar answered Sep 23 '22 19:09

stevemegson