让我们简化模型。
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;
}
}
}
主要功能是让Container container = new Container();
为container.PNG和Queue.Enqueue(container)
生成PNG
使用using()子句根本不起作用。
虽然这种情况重复了大约40次(因此而异),但它会引发异常。有时它是OutOfMemoryException,有时它就像“GDI +正常错误”(我不确定它是如何完全用英语,我只是翻译它)。 但是,如果我尝试捕捉异常而忽略它,它仍然可以继续产生更多但不是无限制的,只是更多的前进。 任务管理器中显示的占用内存仅在抛出第一个异常时大约为600 - 700 MB,最终停止在大约1.2 GB。我试过这个:
while (true)
{
Bitmap b = new Bitmap(4500, 5000);
list.Add(b);
Invoke((MethodInvoker)delegate { textBox1.Text = list.Count.ToString(); });
}
虽然已经为程序分配了99%的内存(大约11GB),但它永远不会抛出任何异常,而且所有发生的事情都是textBox1中不再引发的数字。
避免这种情况的方法可能不是产生这么多东西,但我仍然想知道内部原则和理由,并感谢你的帮助。
答案 0 :(得分:0)
byte[] PNG = new byte[pngStream.Length];
分配大部分内存来存储图像。
跟随调用它没用,你已经处理好了流。
GC.Collect();
GC.WaitForPendingFinalizers();
PNG数组使用的内存无法释放,因为函数返回中存在活动引用。
我建议返回一个流而不是一个字节数组。
否则,在您调用方法Produce
之后,请记得在再次调用之前删除对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();
}
平台编译会影响最大可用内存: