Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么System.Drawing.dll中存在C#OutOfMemory异常?_C#_.net_Winforms - Fatal编程技术网

为什么System.Drawing.dll中存在C#OutOfMemory异常?

为什么System.Drawing.dll中存在C#OutOfMemory异常?,c#,.net,winforms,C#,.net,Winforms,让我们简化模型 class Container { //other members public byte[] PNG; } class Producer { public byte[] Produce(byte[] ImageOutside) { using (MemoryStream bmpStream = new MemoryStream(ImageOutside), pngStream = new MemoryS

让我们简化模型

class Container
{
    //other members
    public byte[] PNG;
}

class Producer
{
    public byte[] Produce(byte[] ImageOutside)
    {
        using (MemoryStream bmpStream = new MemoryStream(ImageOutside), 
            pngStream = new MemoryStream())
        {
            System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(bmpStream);
            bitmap.Save(pngStream, System.Drawing.Imaging.ImageFormat.Png);
            pngStream.Seek(0, System.IO.SeekOrigin.Begin);
            byte[] PNG = new byte[pngStream.Length];
            pngStream.Read(PNG, 0, (int)pngStream.Length);
            bitmap.Dispose();
            GC.Collect();
            GC.WaitForPendingFinalizers();
            return PNG;
        }
    }
}
主函数保持make
Container=newcontainer()
为container.PNG和
Queue.Enqueue(container)
use using()子句根本不起作用

虽然这个过程重复了大约40多次(不同),但它抛出了一个异常。有时是OutOfMemoryException,有时是“GDI+正常错误”(我不确定它在英语中的确切含义,我只是翻译了一下)。 但是,如果我尝试捕捉异常并简单地忽略它,它仍然可以继续产生更多,但不是无限的,只是更向前。 当抛出第一个异常时,任务管理器中显示的占用内存仅为600-700 MB,最终在1.2GB左右停止。我试过这个:

while (true)
{
    Bitmap b = new Bitmap(4500, 5000);
    list.Add(b);
    Invoke((MethodInvoker)delegate { textBox1.Text = list.Count.ToString(); });
}
虽然99%的内存(约11GB)已分配给该程序,但它从未引发任何异常,所发生的只是textBox1中的数字不再上升


避免这种情况的方法可能不是生产这么多东西,但我仍然想知道内部原理和原因,并感谢您的帮助。

with
byte[]PNG=new byte[pngStream.Length]分配大量内存来存储图像

后续调用无效,您已处理该流

GC.Collect();
GC.WaitForPendingFinalizers();
无法释放PNG数组使用的内存,因为函数return中有活动引用

我建议返回一个流,而不是一个字节数组

否则,在调用方法
product
后,记得在再次调用之前删除对PNG的引用

样本:

while (true)
{
    Byte[] b = new Byte[1000];
    b = this.Produce(b);
    //Use your array as you need, but you can't assign it to external property, otherwise memory cannot be released 
    b = null; //remove the reference, (in reality, in this example assign null is not necessary, because b will be overwritten at next loop.
    GC.Collect(); //Force garbage collector, probably not necessarry, but can be useful
    GC.WaitForPendingFinalizers();
}
平台编译可能会影响最大可用内存:

  • 在32位应用程序中,可用内存最多为2 GiB
  • 在64位应用程序中,您有2个Tib的可用内存,但 单个对象(类)不能超过2 Gib
  • 在UWP应用程序中,依赖于 装置
  • 当你启动应用程序时,任何CPU都会被及时编译, 并且可以运行32位和64位,这取决于机器架构 和系统配置

    • 带有
      字节[]PNG=新字节[pngStream.Length]分配大量内存来存储图像

      后续调用无效,您已处理该流

      GC.Collect();
      GC.WaitForPendingFinalizers();
      
      无法释放PNG数组使用的内存,因为函数return中有活动引用

      我建议返回一个流,而不是一个字节数组

      否则,在调用方法
      product
      后,记得在再次调用之前删除对PNG的引用

      样本:

      while (true)
      {
          Byte[] b = new Byte[1000];
          b = this.Produce(b);
          //Use your array as you need, but you can't assign it to external property, otherwise memory cannot be released 
          b = null; //remove the reference, (in reality, in this example assign null is not necessary, because b will be overwritten at next loop.
          GC.Collect(); //Force garbage collector, probably not necessarry, but can be useful
          GC.WaitForPendingFinalizers();
      }
      
      平台编译可能会影响最大可用内存:

      • 在32位应用程序中,可用内存最多为2 GiB
      • 在64位应用程序中,您有2个Tib的可用内存,但 单个对象(类)不能超过2 Gib
      • 在UWP应用程序中,依赖于 装置
      • 当你启动应用程序时,任何CPU都会被及时编译, 并且可以运行32位和64位,这取决于机器架构 和系统配置

      您需要处理创建的每个位图。你可能已经用完了图形句柄。While(true)是一个无限循环,它将以最快的速度运行,直到你中断为止。而空的
      使用带有空文件夹的
      也没有任何作用。不幸的是,
      系统.Drawing
      类有一个坏习惯,即有效地执行“是特定的坏情况a吗?我将抛出此异常。是特定的坏情况b吗?我将抛出该异常。对于任何其他错误情况,我将猜测它是OutOfMemory”-也就是说,当基本问题与内存无关时,它通常会引发此异常。@Hans Passant我不明白,因为我需要的只是字节[],我已经在处理流之前处理了位图。为什么流必须保持可读性?什么是潜在的蒸汽?没有下划线。您一直在列表中添加大型位图;这很可能不是关于内存,而是关于“GDI句柄”。在任务管理器中观察它们不断上升,直到您的任务结束。您需要处理创建的每个位图。你可能已经用完了图形句柄。While(true)是一个无限循环,它将以最快的速度运行,直到你中断为止。而空的
      使用带有空文件夹的
      也没有任何作用。不幸的是,
      系统.Drawing
      类有一个坏习惯,即有效地执行“是特定的坏情况a吗?我将抛出此异常。是特定的坏情况b吗?我将抛出该异常。对于任何其他错误情况,我将猜测它是OutOfMemory”-也就是说,当基本问题与内存无关时,它通常会引发此异常。@Hans Passant我不明白,因为我需要的只是字节[],我已经在处理流之前处理了位图。为什么流必须保持可读性?什么是潜在的蒸汽?没有下划线。您一直在列表中添加大型位图;这很可能不是关于内存,而是关于“GDI句柄”。在任务管理器中观察它们不断上升,直到您的任务完成。。