为啥在比较列表项时出现内存不足异常?
Posted
技术标签:
【中文标题】为啥在比较列表项时出现内存不足异常?【英文标题】:Why i'm getting out of memory exception when comparing Lists items?为什么在比较列表项时出现内存不足异常? 【发布时间】:2015-03-29 01:21:04 【问题描述】:在绘制事件中,我绘制了一个矩形,然后将矩形区域内的像素坐标添加到列表中:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
if (cloudPoints != null)
if (DrawIt)
e.Graphics.DrawRectangle(pen, rect);
pointsAffected = cloudPoints.Where(pt => rect.Contains(pt));
CloudEnteringAlert.pointtocolorinrectangle = pointsAffected.ToList();
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height, PixelFormat.Format32bppArgb);
CloudEnteringAlert.Paint(e.Graphics, 1, 200, bmp);
我正在绘制一个矩形,它是 rect(Rectangle) 变量,并仅将矩形区域内的像素坐标分配给 pointsAffected List ! cloudPoints 包含整个图像的所有像素坐标!!!但是 pointsAffected 只包含矩形区域内的像素坐标。
然后是鼠标向上事件:
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
StreamWriter w = new StreamWriter(@"c:\diff\diff.txt");
pixelscoordinatesinrectangle = new List<Point>();
pixelscoordinatesinrectangle = pointsAffected.ToList();
DrawIt = false;
for (int i = 0; i < trackBar1FileInfo.Length; i++)
DrawIt = true;
trackBar1.Value = i;
LoadPictureAt(trackBar1.Value, sender);
pictureBox1.Load(trackBar1FileInfo[i].FullName);
ConvertedBmp = ConvertTo24(trackBar1FileInfo[trackBar1.Value].FullName);
ConvertedBmp.Save(ConvertedBmpDir + "\\ConvertedBmp.bmp");
mymem = ToStream(ConvertedBmp, ImageFormat.Bmp);
backTexture = TextureLoader.FromStream(D3Ddev, mymem);
scannedCloudsTexture = new Texture(D3Ddev, 512, 512, 1, Usage.Dynamic, Format.A8R8G8B8, Pool.Default);
Button1Code();
pictureBox1.Refresh();
newpixelscoordinates = new List<Point>();
newpixelscoordinates = pointsAffected.ToList();
if (pixelscoordinatesinrectangle != null && newpixelscoordinates != null)
IEnumerable<Point> differenceQuery =
pixelscoordinatesinrectangle.Except(newpixelscoordinates);
// Execute the query.
foreach (Point s in differenceQuery)
w.WriteLine("The following points are not the same" + s);
else
am1 = pixelscoordinatesinrectangle.Count;
am2 = newpixelscoordinates.Count;
//MessageBox.Show(pixelscoordinatesinrectangle.Count.ToString());
w.Close();
一旦我完成绘制矩形,我将创建一个新的 List 实例并将矩形区域中的像素存储在 pixelcoordinatesinrectangle List 中。
然后我循环遍历 trackBar1FileInfo,其中包含例如来自硬盘的 5000 个图像文件名。
这是问题部分:
pictureBox1.Refresh();
newpixelscoordinates = new List<Point>();
newpixelscoordinates = pointsAffected.ToList();
if (pixelscoordinatesinrectangle != null && newpixelscoordinates != null)
IEnumerable<Point> differenceQuery =
pixelscoordinatesinrectangle.Except(newpixelscoordinates);
// Execute the query.
foreach (Point s in differenceQuery)
w.WriteLine("The following points are not the same" + s);
else
am1 = pixelscoordinatesinrectangle.Count;
am2 = newpixelscoordinates.Count;
我正在为图片框1 进行刷新,因此它会将每个图像转到绘制事件,并创建一个新列表 pointsAffected 每次都会有不同的像素坐标。
所以 newpixelscoordinates 应该是每个循环迭代的新像素坐标。
然后我比较 Lists newpixelscoordinates 和 pixelcoordinatesinrectangle 的不同项目。
并将那些不一样的写到一个文本文件中。
所以我得到了一个非常大的文本文件,其中有许多像素坐标在两个列表中都不相同。
问题是:
我做的比较对吗?我想将一个列表索引与其他列表索引进行比较。
例如,在索引 0 的新像素坐标列表中,如果我有 x = 233 y = 23,而在索引 0 的像素坐标直角列表中,则 x = 1 y = 100 然后将其写入文本文件中。
我想要做的是对照其他列表项检查整个列表项,如果某些项不相同,则将此项写入文本文件。
下一次迭代 new image new Lists 用新的像素坐标做同样的比较。
当我第一次绘制矩形时,List pixelcoordinatesinrectangle 并没有改变它存储的第一个像素坐标。每次只有 List newpixelscoordinates 改变,每次迭代都应该改变。
我得到的例外是在线:
newpixelscoordinates = new List();
我添加了这一行,因为我想也许我没有每次都清除它,但它没有帮助。
在添加此行之前,异常就在行上:
newpixelscoordinates = pointsAffected.ToList();
异常是:OutOfMemoryException: Out of memory
System.OutOfMemoryException was unhandled
HResult=-2147024882
Message=Out of memory.
Source=System.Drawing
StackTrace:
at System.Drawing.Graphics.CheckErrorStatus(Int32 status)
at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height)
at System.Drawing.Graphics.DrawImage(Image image, Rectangle rect)
at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.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)
InnerException:
【问题讨论】:
(抱歉,忍不住了,)我怀疑你的内存用完了。 仔细检查所有界限。您可以通过无效的矩形/边界来获得 OOM 异常。就像宽度/高度 确实....在 C#/VB.net 中,默认情况下框架会处理很多资源管理,但是仍然有大量非托管资源(特别是当您处理将内容绘制到屏幕上)。正如@TyCobb 所说,确保你已经完成了你的对象,然后再处理它们,但一定要处理它们,否则你会遇到你遇到的东西。例如,在您的MouseUp
事件中,我会考虑在您调用 w.Close();
的同一点处理一堆东西
【参考方案1】:
在您的代码中,必须释放一些对象以释放内存,例如函数pictureBox1_Paint
中的Bitmap
对象、pictureBox1_MouseUp
中的StreamWriter
对象。可能还有更多。
对于实现IDisposable接口的托管对象 ,您必须及时处理它们以释放非托管内存。 GC 并不是专门用来管理非托管资源的,使用 unmanage 内存不会增加 GC 压力,也不会触发 GC 动作,这就是为什么会出现内存不足异常的原因。
用代码分析编译你的程序,它会告诉你哪些对象需要在警告中处理。将它们放在using 块中。
【讨论】:
另外,您可以使用'using' 语句在完成这些 IDisposable 对象后自动释放它们。以上是关于为啥在比较列表项时出现内存不足异常?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Android-Espresso 运行多个测试时出现内存不足异常
使用 EPPlus 库从 SQL Server 导出到 Excel 时出现“内存不足”异常
在 ListView 中使用 LazyList 时出现内存不足错误 [重复]