内存耗尽

5 .net c# memory

我这里有一些代码

   private void Run()
    {
        MyClass c = new MyClass();
        c.Load(somepath1);
        using (StreamReader sr = new StreamReader(filepath))
        {
            string line = string.Empty;
            while ((line = sr.ReadLine()) != null)
            {
                using (Bitmap B = new Bitmap(line))
                {
                    Point p = SomeMethod(ref c, new Point());
                    using (MemoryStream ms = new MemoryStream())
                    {
                        B.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
                        using (Bitmap T = new Bitmap(new Bitmap(Image.FromStream(ms))))
                        using (Graphics g = Graphics.FromImage(T))
                        {
                            g.DrawEllipse(new Pen(Brushes.Red, 4), p.X - 5, p.Y - 5, 10, 10);
                            FileInfo fi = new FileInfo(somepath2);
                            T.Save(Path.Combine(somepath3, fi.Name));
                        }
                    }
                }
            }
        }
    } 
Run Code Online (Sandbox Code Playgroud)

和函数SomeMethod是:

    Point SomeMethod(ref MyClass c, Point mid)
    {
        float[] Mat = new float[9];
        Point p;

        c.Method1(Mat);
        c.Method2(Mat, out p);

        return p;
    }
Run Code Online (Sandbox Code Playgroud)

MyClass是:

public class MyClass
{
    public void Method1(float[] Mat, out Point point)
    {
        //calculation point from values in Mat
    }

    public void Method2(float[] Mat)
    {
        //Do some Operation in Mat
    }

    public void Load(string FileName)
    {
        //Do Some Data Loading From a small file about 400 byte
    }
}
Run Code Online (Sandbox Code Playgroud)

StreamReader sr在文件路径中打开一个文件,该文件有大约400行图像位置,我根据我的计算读取它们并在它们上绘制一些东西,我没有使用任何外部库或任何不安全的代码.问题是为什么我的内存不足?

- - - - - - -编辑 - - - - - - - - - -

当程序启动时它使用大约20mb的内存,在调用Run后,内存使用率开始增加,如果我运行大约200个图像,内存大约1.7Gb,Run函数完成工作,内存使用量回到20mb

------------ EDIT ------------在MemoryStream中保存Bitmap B是因为图形不能使用Indexed像素格式图像.主要问题是垃圾收集器在这做什么?我没有应该留在内存中的对象.

- - - - - 编辑 - - - - - - - -

例外是:

System.OutOfMemoryException was unhandled
  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.Bitmap..ctor(Image original, Int32 width, Int32 height)
       at System.Drawing.Bitmap..ctor(Image original)
       at WindowsFormsApplication1.Form1.buttonrun1_Click(Object sender, EventArgs e) in C:\Users\hamidp\Desktop\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:line 115
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.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.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at WindowsFormsApplication1.Program.Main() in C:\Users\hamidp\Desktop\WindowsFormsApplication1\WindowsFormsApplication1\Program.cs:line 17
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 
Run Code Online (Sandbox Code Playgroud)

和行抛出的异常:

using (Bitmap T = new Bitmap(new Bitmap(Image.FromStream(ms))))

- - - - - - - - - -编辑 - - - - - - - - - - - -

我还加了一行GC.Collect();

while ((line = sr.ReadLine()) != null)

同样的错误又发生了.

Guf*_*ffa 14

最有可能因为你分配了很多你没有处理的对象.

在这一行:

using (Bitmap T = new Bitmap(new Bitmap(Image.FromStream(ms))))
Run Code Online (Sandbox Code Playgroud)

FromStream调用分配了一个您从未处理过的位图.内部Bitmap构造函数创建了另一个您从未处理过的位图.它只是Bitmap被处理的外层.

请记住,using块仅处理您在该语句中直接分配的对象,而不是您创建的任何对象,并将其用作创建该对象的参数.

当您只使用已加载的位图时,我没有看到从位图创建位图的逻辑:

using (Bitmap T = (Bitmap)Image.FromStream(ms))
Run Code Online (Sandbox Code Playgroud)

在这一行:

g.DrawEllipse(new Pen(Brushes.Red, 4), p.X - 5, p.Y - 5, 10, 10);
Run Code Online (Sandbox Code Playgroud)

你创建一个Pen永远不会被处置的对象.把它放在一个使用块中:

Using (Pen red = new Pen(Brushes.Red, 4)) {
  g.DrawEllipse(red, p.X - 5, p.Y - 5, 10, 10);
}
Run Code Online (Sandbox Code Playgroud)

  • @Adam Norberg:垃圾收集器在终结器运行之前无法删除任何未处理的对象,并且只有一个后台线程一次运行一个终结器.如果它无法以与创建图像相同的速率执行终结器,则内存将填满. (5认同)
  • 但这不应该是相关的.对象很快就无法访问,垃圾收集器应该可以拾取它们,终结器处理它们,然后它们会在下一次垃圾收集器扫描时抛出(最终化对象不能立即扫描).我不明白为什么会留下2GB无法收集的资源. (2认同)

小智 0

我只是替换GC.Collect()GC.WaitForPendingFinalizers(),问题就解决了。