【发布时间】:2017-03-02 11:21:13
【问题描述】:
让我们简化模型。
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;
}
}
}
main函数不断使Container container = new Container();为container.PNG生成PNG,Queue.Enqueue(container)
使用 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 中的数字不再增加。
避免这种情况的方法可能是不要产生那么多东西,但我还是想知道内部原理和原因,谢谢你的帮助。
【问题讨论】:
-
您需要处理创建的每个位图。您可能用完了图形句柄。
-
While(true) 是一个无限循环,它将尽可能快地运行,直到你中断。带有空文件夹的空
using也不执行任何操作。 -
不幸的是,
System.Drawing类有一个坏习惯,即有效地执行“是不是特定的糟糕情况 a?我会抛出这个异常。是不是特定的糟糕情况 b?我会抛出那个异常. 对于任何其他错误情况,我猜它是 OutOfMemory” - 即当底层问题与内存无关时,它经常抛出此异常。 -
@Hans Passant 我不明白,因为我只需要字节 [],我已经在流处理之前处理了位图。为什么流必须保持可读?什么是潜在蒸汽?没有下划线。
-
您不断将大位图添加到您的列表中;这很可能不是关于内存,而是关于 'GDI 句柄'。观看他们在任务管理器中向上和向上直到你离开他们..