Timer and memory leak

As a newbie to c# and vis studio am having trouble with the following timer function. When i watch it in task manager i can see the memory used increasing steadily per unit time:

I presume its something to do with not freeing up the objBitmap but not sure.
As you may guess, the timer is there to animate the taskbar icon.

Suggestions Please..
Thanks
Shaun

private void iconTimer_Tick(object sender, System.EventArgs e)

{

Bitmap objBitmap;

Icon objIcon;

objBitmap = new Bitmap(imageList1.Images[iconRef]);

objIcon = System.Drawing.Icon.FromHandle(objBitmap.GetHicon());

notifyIcon1.Icon=objIcon;

iconRef++;

if (iconRef==16)

iconRef=0;

}



Answer this question

Timer and memory leak

  • mom bot

    If I create a simple Windows Forms project with a Forms.Timer control my app leaks 8K of memory every tick.

    I am using C#. The 2003 Dev Environment 7.1.3088, and the 1.1 Framework with SP1.

    The app has no other controls but the timer, and does nothing in the tick callback.

    I have searched many forums to see if anyone else is having this problem, but I haven't found an answer yet.

    Does anyone know why this would happen

    Thanks


  • ShootingStar

    It happens for the same reason that any memory leaks happen, but luckily, you know exactly where to look -- in the Tick event. Post the code inside that event if you want more help.

  • Lecenio

    It looks like you're leaking the bitmap and unintentionally the Icon, even though you're calling Dispose on it. 

    - Calling bitmap.GetHicon() creates a new icon, therefore you're free to dispose the bitmap.
    - Calling dispose on an icon that was created "FromHandle" doesnt free associated GDI object as the Icon class doesnt think it owns the memory.


    Here's a simpler example where "this" is the form.  I've placed it on a button click and have verified that the GDI object count does not increase.  How I checked is detailed in part three of this article.


    private void button1_Click(object sender, System.EventArgs e) {

    using (Bitmap b = new Bitmap(16,16)) {
       
    using (Graphics g = Graphics.FromImage(b)) {
             g.Clear(Color.Red);
        }
        Icon icon = Icon.FromHandle(b.GetHicon());
        Icon oldIcon =
    this.Icon;
       
    this.Icon = icon;
       
    // unfortunately, since the icon isnt created using one of the
       
    // public Icon constructors, the Icon class doesnt think it
       
    // owns this memory, so wont make this call. 
        
    // This applies only for the FromHandle method.
      
       NativeMethods.DestroyIcon(new HandleRef(this, oldIcon.Handle));

    } // the using statement Disposes the bitmap here. It should be disposed here because GetHicon creates a copy.

    }

    // p/invoke definition for DestroyIcon
    internal
    class NativeMethods {
       [DllImport("user32.dll", EntryPoint="DestroyIcon", CharSet=CharSet.Auto, ExactSpelling=
    true)]
      
    public static extern bool DestroyIcon(HandleRef hIcon);
    }


     

    If you have the icons already I encourage using the stream constructors instead.  This way you're not doing the imagelist->bitmap->icon conversion, which in the process makes three copies of the image.

    You can add the icons as an embedded resource to your project really easily.  For more details on how to use them, check out the Wonders of Windows Forms article on .Net Resource Basics.

    Hope this helps sort things out,
    Jessica
    Developer, Windows Forms Team

  • cchandru1974

    You are correct, you are not disposing of the Bitmap nor the Icon.

    If the ImageList only contains Bitmaps then you could probably do this:


    Icon.FromHandle(((Bitmap)imageList1.Images[iconRef]).GetHicon());
     


    That way you are not creating a new bitmap each time.

    You will also need to call Dispose on previous Icon.



    Icon previousIcon = notifyIcon1.Icon;

    notifyIcon1.Icon = objIcon;

    previousIcon.Dispose();

     




  • JayNeu

    Thanks for the reply and sory for my delay in trying your suggestion.
    however - it doesnt seem to do the job!
    The memory still leaks away as before :(

    Do you have any more suggestions please
    Shaun


  • Timer and memory leak