为啥在比较列表项时出现内存不足异常?

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 时出现“内存不足”异常

为啥使用JAVA的时候老显示内存不足?

在 ListView 中使用 LazyList 时出现内存不足错误 [重复]

安装 guzzlehttp/guzzle 时出现内存不足和未配置交换的问题

内存不足异常