2011-12-16 40 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); 
    }