C#、XNA、FileStream、内存不足异常

C#、XNA、FileStream、内存不足异常,c#,out-of-memory,xna-4.0,C#,Out Of Memory,Xna 4.0,我正在尝试将XNA游戏的每个渲染帧保存到硬盘上。所以在每一帧中,我称之为代码: protected override void LoadContent() { .... colorRT = new RenderTarget2D(GraphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Color, DepthFormat.Depth

我正在尝试将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调用来尝试解决这个问题,但这并没有改变任何事情


有人知道我做错了什么吗?

听起来像是,如果你对每一帧(每秒很多帧)都这样做,你正在写3幅图像-可能会有一个队列将其写入磁盘,这会导致备份程序运行的次数越多,从而导致问题。

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


不幸的是,解决方案是创建自己的纹理保存例程。

强制执行
GC.Collect
将只收集符合条件的内容……如果内存压力很大,GC算法将更经常地为您执行此操作,因此这是很少的解决方案

它还表明,您假定
流s=File.Open
部分是问题所在。它被包装在
using
语句中,随后立即超出范围,这意味着它被正确地处理,并且可能会作为Gen-0对象保留—这意味着GC可以快速、高效地收集

您还有两个问题:用于调用save to 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);
    }

顺便说一句,
using
语句为您调用Dispose,如果您进行Dispose,则不需要关闭或刷新。问题可能在于您一直保存PNG?或者
xxRT
变量一直在增长。文件流每次都被正确地删除。是的,我也这么认为,但我不这么认为e这段代码怎么会导致outOfMemory异常。如果我注释掉它,一切都会正常运行。你不需要使用Flush、Close和Dispose来使用。你有什么for循环吗?这段代码是如何调用的?在XNA中,有一些每秒调用数百次的方法来刷新图形。frameNumber++是什么?如果unter正在增长,这就是你的问题。将加载内容的代码移动到一个只调用一次的方法。@oleksii:他希望每帧输出一次,所以加载内容时不能只运行一次。“framenumber”仅用于文件名。该代码每帧只调用一次。它正好位于我的正常绘图例程的末尾场景+1在我看来似乎是合理的,因为我自己无法分析它。也许可以尝试将保存次数限制为每秒一次左右。看看这是否有帮助。也许值得注意的是,解决方案可能是限制帧速率,或者不保存每一帧。当我注释掉代码时,它以大约300 fps的速度运行。打开代码后,它仅以每秒一次的速度运行大约4-5 fps,所以我怀疑它是否会在某个地方排队。@Mat假设这不是问题,您能详细介绍一下OP中的
xxRT
变量吗?它们保存PNG,因此可能有文件句柄和内部缓冲区。yap-该线程中的bmpWriter类完成了此任务!谢谢:)您应该更改流名称…:)