2011-12-16 38 views
2

我试图将我的XNA游戏的每个渲染帧保存到硬盘。因此,在每一帧,我把这个代码:C#,XNA,FileStream,内存不足异常

 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++; 

,但如果这个代码是,内存消耗上升,上升,半分钟左右后,我得到了一个内存溢出异常。我添加了flush,close,dispose和GC调用来试图解决这个问题,但它并没有改变任何事情。

任何人都知道我在做什么错?

+1

正如顺便说一句,在`using`语句调用Dispose你,如果你既不处置关闭或冲洗是必需的。这个问题可能与您继续保存PNG的事实有关?或者`xxRT`变量一直在增长。文件流正在摆脱每次正确。 – 2011-12-16 11:28:28

+0

是的,这就是我thoght太,但我不知道这个代码如何可以导致outOfMemory异常。如果我将它注释掉,一切运行正常 – Mat 2011-12-16 11:29:58

+0

您不需要使用*使用*来使用Flush,Close和Dispose。你有什么* for *循环的地方?这个代码是如何调用的? XNA中的AFAIK有一些方法被称为每秒数百次刷新图形。 ** frameNumber ++ **那是什么?如果这个计数器增长,那就是你的问题。将加载内容的代码移动到一次调用的方法。 – oleksii 2011-12-16 11:30:48

回答

5

根据thisTexture2D.SaveAsJpeg(以及Texture2D.SaveAsPng)有内存泄漏。

解决方案是(不幸)创建你自己的纹理保存程序。

4

听起来像这样,如果你为每一帧这样做(即每秒很多),你正在写3个图像 - 可能有一个队列建立起来写入磁盘,这是备份越多的程序运行导致这个问题。

0

强制GC.Collect只会收集什么资格被收集...如果内存压力较高时,GC算法将会更频繁地为你反正这样做,所以这是很少的解决方案。

这也表明你认为Stream s = File.Open部分是问题所在。这包含在using声明中,之后立即超出范围,这意味着它正在被正确处置,并且可能会保留为Gen-0对象 - 这意味着GC进行快速,高效的收集。

您还有两个问题区域:用于调用保存到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); 
    }