I have a few SQL databases which has a table that store images using varbinary
datatype.
On button click, it will remove all existing images except the first three images from the ImageList
control and add all new images to the ImageList
on my form.
There is a TreeView
that uses this ImageList
.
I've been getting:
Out of memory exception
...if I click the button many times on the same database.
Simplified code:
if(imageList1.Images.Count > 3)
{
for (int i = imageList1.Images.Count - 1; i > 2; i--)
{
imageList1.Images.RemoveAt(i);
}
}
int counter = 0;
foreach (DataRow dr in dataset.Tables[0].Rows)
{
if (dr["ImageField"] != DBNull.Value)
{
byte[] imageData = (byte[])dr["ImageField"];
MemoryStream ms = new MemoryStream(imageData, 0, imageData.Length);
Bitmap img = new Bitmap(ms);
imageList1.Images.Add("Image" + counter, img);
img.Dispose();
ms.Dispose();
counter++;
}
}
StackTrace:
at System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)
at System.Drawing.Font.ToLogFont(Object logFont)
at System.Drawing.Font.ToHfont()
at System.Windows.Forms.Control.FontHandleWrapper..ctor(Font font)
at System.Windows.Forms.OwnerDrawPropertyBag.get_FontHandle()
at System.Windows.Forms.TreeView.CustomDraw(Message& m)
at System.Windows.Forms.TreeView.WmNotify(Message& m)
at System.Windows.Forms.TreeView.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd, Message& m)
at System.Windows.Forms.Control.WmNotify(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Control.DefWndProc(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.TreeView.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, Int32 wParam, Int32 lParam)
at System.Windows.Forms.Control.EndUpdateInternal(Boolean invalidate)
at System.Windows.Forms.TreeView.ImageListChangedHandle(Object sender, EventArgs e)
at System.EventHandler.Invoke(Object sender, EventArgs e)
at System.Windows.Forms.ImageList.OnChangeHandle(EventArgs eventargs)
at System.Windows.Forms.ImageList.ImageCollection.Add(Original original, ImageInfo imageInfo)
at System.Windows.Forms.ImageList.ImageCollection.Add(String key, Image image)
at Test.MyClass.LoadLibraryImageList()
Why does it throw that exception when the memory usage is very low?
Looks like ImageList
is just the tip of the iceberg, the real problem lays in my extended MultiSelectTreeView
control. After reading this question, I added GC.Collect()
to my code whenever I change the TreeNode
font and voila, problem solved.
From the suggestions, I also dispose unwanted images from my ImageList
before loading a new batch which seems to help lower my GDI counts too. Thanks everyone.