我正在尝试将我的XNA游戏的每个渲染帧保存到硬盘。所以在每一帧中,我都会调用这段代码:
protected override void LoadContent()
{
....
colorRT = new RenderTarget2D(GraphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Color, DepthFormat.Depth24);
lightRT = new RenderTarget2D(GraphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Color, DepthFormat.None);
specRT = new RenderTarget2D(GraphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Color, DepthFormat.None);
....
}
using (Stream stream = File.OpenWrite("color_"+frameNumber+".png"))
{
colorRT.SaveAsPng(stream, colorRT.Width, colorRT.Height);
stream.Flush();
stream.Close();
stream.Dispose();
}
using (Stream stream = File.OpenWrite("light_" + frameNumber + ".png"))
{
lightRT.SaveAsPng(stream, lightRT.Width, lightRT.Height);
stream.Flush();
stream.Close();
stream.Dispose();
}
using (Stream stream = File.OpenWrite("spec_" + frameNumber + ".png"))
{
specRT.SaveAsPng(stream, specRT.Width, specRT.Height);
stream.Flush();
stream.Close();
stream.Dispose();
}
System.GC.Collect();
frameNumber++;
但是如果这个代码打开了,内存消耗会上升和上升,大约半分钟后我会得到一个outOfMemory异常。我添加了flush,close,dispose和GC调用来尝试解决问题,但它并没有改变。
任何人都知道我做错了什么?
答案 0 :(得分:5)
根据this Texture2D.SaveAsJpeg
(以及Texture2D.SaveAsPng
)内存泄漏。
解决方案(不幸的是)创建自己的纹理保存例程。
答案 1 :(得分:4)
听起来如果你为每一帧(即每秒很多)执行此操作,那么你正在编写3个图像 - 可能有一个队列正在构建将其写入磁盘,而这正在备份,程序运行的次数越多问题。
答案 2 :(得分:0)
强制GC.Collect
只会收集有资格收集的内容......如果内存压力很高,GC算法会更频繁地为您执行此操作,因此很少< / strong>解决方案。
它还表明您认为Stream s = File.Open
部分是问题所在。这包含在using
语句中,之后立即超出范围,这意味着它被正确处理,也可能保留为Gen-0对象 - 这意味着GC快速,高效地收集。 / p>
您还有两个问题区域:用于调用保存到PNG的xxRT
变量,以及每帧保存三个PNG的行为。
另外,您可以改进代码的格式:
using (Stream stream = File.OpenWrite("color_"+frameNumber+".png"))
using (Stream stream2 = File.OpenWrite("light_" + frameNumber + ".png"))
using (Stream stream3 = File.OpenWrite("spec_" + frameNumber + ".png"))
{
colorRT.SaveAsPng(stream, colorRT.Width, colorRT.Height);
lightRT.SaveAsPng(stream2, lightRT.Width, lightRT.Height);
specRT.SaveAsPng(stream3, specRT.Width, specRT.Height);
}