LINQed IN

Blog by Troy Magennis on Software Architecture, Development and Management

About the author

Troy Magennis is a software developer living in Seattle, WA. Troy is a Microsoft MVP, the author of many articles, and the founder of HookedOnLINQ.com, a LINQ specific wiki reference site.
E-mail me Send mail

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2014

Tips for WinForms Memory and Painting Debugging

Every now and then I come across a Windows Forms application that has memory leak, or graphic resource leak issues. In managed environments like .NET, some developers overlook that many components wrap un-managed finite resources.  I worked with a fellow developer Mike Zhang today, and because of the difficulties in replicating the issue, we decided that a full pass through the entire source code fixing these issues was our best shot at solving a niggling production issue. After today, here are our top 4 tips and the first steps to ensuring you have a well behaved Windows Forms .NET application.

Begin Update / End Update (Blank, unpainted regions of the screen)

Many Windows controls have a BeginUpdate and EndUpdate methods. These inhibit any Paint events being called when a lot of data is being added to a ListView for example. Big trouble occurs if an EndUpdate isn’t called matching a BeginUpdate! Most general case, is an exception occurs after the begin, but before the EndUpdate gets called.

To Fix: Do a solution wide search for “BeginUpdate”; Go through the result list (yes, EVERY one of them) and ensure that a the EndUpdate is wrapped in a Finally block.

BAD

   1:  this.BeginUpdate();
   2:  // lots of work, including work that may throw an exception!
   3:  // ...
   4:  this.EndUpdate();

GOOD

   1:  this.BeginUpdate();
   2:  try
   3:  {
   4:       // lots of work, including work that may throw an exception!
   5:  }
   6:  finally
   7:  {
   8:      // EndUpdate called even in the case of an Exception in the lots of work above.
   9:      this.EndUpdate();
  10:  }

Pen, Brush and Graphic Resources (Resource leak)

Even in .NET, a lot of managed code uses unmanaged resources. These managed wrappers implement the IDisposible pattern, where the Dispose method nicely releases all unmanaged resources. However – What if Dispose doesn’t get called? Either because Garbage Collection in .NET is happens on its own non-deterministic timetable, some external reference keeps an object alive, or an exception occurs and Dispose is never called. This manifests itself as areas that don’t draw properly or have an enclosed red cross.

To Fix: Do a solution wide search for “Graphic ”, “Pen “ and “Brush “; Go through the result list (yes, EVERY one of them) and ensure that the scope of the Brush, Pen or Graphic is within a using clause, or a try/finally block.

Read: "using" statement reference on MSDN: http://msdn2.microsoft.com/en-us/library/yh598w02.aspx

BAD

   1:      Graphics g = Graphics.FromImage(sourceImage);
   2:      Pen pen = new Pen();
   3:      // lots of work, including work that might fail
   4:      g.DrawRectangle(pen, 10, 10, 100, 100);
   5:      throw new Exception();
   6:      pen.Dispose(); // never called
   7:      g.Dispose(); // never called

GOOD

   1:      using(Graphics g = Graphics.FromImage(sourceImage))
   2:      {
   3:          using(Pen pen = new Pen())
   4:          {
   5:              // lots of work, including work that might fail
   6:              g.DrawRectangle(pen, 10, 10, 100, 100);
   7:              throw new Exception();
   8:           } // calls pen.Dispose() in all cases
   9:      } // calls g.Dispose() in ALL cases

Manual Event Wiring Up and Object Lifetime (memory and resource leak)

This is without a doubt the most common (and some say only common) memory leak on .NET applications. If your component subscribes to an event in ANOTHER component or class, you must –

a) Unhook yourself in your Dispose method for the form or class you subscribed FROM

b) Avoid multiple hookups to an event if your form is opened, or called multiple times

Tips:

a) Hookup events using the Forms designer when possible; This automatically handles events in the proper way

b) To be sure multiple hookups don’t accidently occur, remove yourself from an event before hooking your event up (this is safe, even the first time) –

BAD
ValidationGlobalManager.OnValidate += new My ValidationHandler(MyValidationFunction);


GOOD
  ValidationGlobalManager.OnValidate -= new My ValidationHandler(MyValidationFunction);
  ValidationGlobalManager.OnValidate += new My ValidationHandler(MyValidationFunction);

c) If you hook up an event outside of InitializeComponent (i.e. NOT through the forms designer), then YOU are responsible for unhooking your event in the Dispose() method of your form.

OnPaint and OnDraw Event Handlers - Call the base. implementation in all cases (unpredictable drawing behavior)

Many controls allow you to implement your own OnDraw and OnPaint event handlers. However, the base.OnDraw(); or base.OnPaint(); methods MUST be called under all conditions, even in the case your code fails with an exception.

To Fix: Do a solution wide search for “OnDraw ” and “OnPaint“; Go through the result list (yes, EVERY one of them) and ensure that

a) the base call is first, so it always runs, OR

b) the base call is protected with a try/finally block

Mike and Troy.


Tags: ,
Categories: C#
Posted by t_magennis on Wednesday, April 09, 2008 4:23 AM
Permalink | Comments (0) | Post RSSRSS comment feed
christian louboutin spiked heels beats by dre red bottom shoes cheap Christian Louboutin Christian Louboutin outlet christian louboutin pumps Christian Louboutin replica Christian Louboutin sale christian louboutin shoes louboutin outlet red bottom shoes Christian Louboutin outlet red bottom shoes Christian Louboutin sale Christian Louboutin shoes sale Christian Louboutin sale Christian Louboutin outlet louboutin outlet Christian Louboutin shoes Jeremy Scott Adidas Jeremy Scott Adidas Air Jordan Pas Cher Air Max Pas Cher Hermes Handbags Outlet Christian Louboutin Shoes Christian Louboutin Outlet Cheap Christian Louboutin Christian Louboutin cheap Christian Louboutin discount Christian Louboutin outlet Christian Louboutin replica Christian Louboutin sale louboutin outlet Louboutin sale Louboutin shoes Christian Louboutin shoes