从SQL数据库添加图像时,ImageList抛出“内存不足”异常

时间:2019-03-26 01:51:36

标签: c# winforms memorystream imagelist

我有一些SQL数据库,其中有一个表,该表使用varbinary数据类型存储图像。

单击按钮后,它将从ImageList控件中删除除前三个图像以外的所有现有图像,并将所有新图像添加到表单上的ImageList

有一个TreeView使用此ImageList

我得到了:

  

内存不足异常

...如果我单击相同数据库上的很多次按钮。

简化代码:

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()

为什么当内存使用率很低时会引发该异常?

2 个答案:

答案 0 :(得分:2)

移除图像时必须将其丢弃(有关说明,请参见this article)。

另外,while循环更简单。只需删除列表中的最后一张图片,直到剩下3张即可。

void RemoveLastImage(ImageList imageList)
{
    var lastIndex = imageList.Images.Count - 1;
    var lastImage = imageList.Images[lastIndex];
    imageList.Images.RemoveAt(lastIndex);
    lastImage.Dispose();
}

while (imageList1.Images.Count > 3)
{
    RemoveLastImage(imageList1);
}

答案 1 :(得分:0)

看起来ImageList只是冰山一角,真正的问题在于我扩展的MultiSelectTreeView控件。阅读此question之后,每当我更改GC.Collect()字体和文字时,我便在代码中添加了TreeNode,问题解决了。

根据建议,我还从ImageList处丢弃了不需要的图像,然后加载了新批次,这似乎也有助于降低我的GDI计数。谢谢大家。