从 SQL 数据库添加图像时,ImageList 抛出 "Out of memory" 异常
ImageList throws "Out of memory" exception when adding images from SQL database
我有几个 SQL 数据库,其中 table 使用 varbinary
数据类型存储图像。
单击按钮时,它将从 ImageList
控件中删除除前三个图像之外的所有现有图像,并将所有新图像添加到我的表单上的 ImageList
。
有一个 TreeView
使用这个 ImageList
。
我得到了:
Out of memory exception
...如果我在相同 数据库上单击按钮多次。
简化代码:
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++;
}
}
堆栈跟踪:
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()
为什么在内存占用很低的时候会抛出那个异常?
删除图像时必须处理它们(有关说明,请参阅 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);
}
看起来ImageList
只是冰山一角,真正的问题在于我扩展的MultiSelectTreeView
控件。阅读此 question 后,每当我更改 TreeNode
字体时,我都会将 GC.Collect()
添加到我的代码中,瞧,问题解决了。
根据建议,我还在加载新批次之前处理了 ImageList
中不需要的图像,这似乎也有助于降低我的 GDI 计数。谢谢大家。
我有几个 SQL 数据库,其中 table 使用 varbinary
数据类型存储图像。
单击按钮时,它将从 ImageList
控件中删除除前三个图像之外的所有现有图像,并将所有新图像添加到我的表单上的 ImageList
。
有一个 TreeView
使用这个 ImageList
。
我得到了:
Out of memory exception
...如果我在相同 数据库上单击按钮多次。
简化代码:
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++;
}
}
堆栈跟踪:
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()
为什么在内存占用很低的时候会抛出那个异常?
删除图像时必须处理它们(有关说明,请参阅 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);
}
看起来ImageList
只是冰山一角,真正的问题在于我扩展的MultiSelectTreeView
控件。阅读此 question 后,每当我更改 TreeNode
字体时,我都会将 GC.Collect()
添加到我的代码中,瞧,问题解决了。
根据建议,我还在加载新批次之前处理了 ImageList
中不需要的图像,这似乎也有助于降低我的 GDI 计数。谢谢大家。