C #, XNA, FileStream, исключение нехватки памяти - PullRequest
2 голосов
/ 16 декабря 2011

Я пытаюсь сохранить каждый отснятый кадр моей игры 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 ]

5 голосов
/ 16 декабря 2011

Согласно эта Texture2D.SaveAsJpeg (а также Texture2D.SaveAsPng) имеет утечку памяти.

Решение состоит (к сожалению) в создании собственной подпрограммы сохранения текстуры.

4 голосов
/ 16 декабря 2011

Похоже, что если вы делаете это для каждого кадра (то есть много в секунду), вы записываете 3 изображения - может быть очередь, создающая очередь для записи на диск, и это резервное копирование по мере того, как программа запускается вперед к вопросу.

0 голосов
/ 16 декабря 2011

Принудительное GC.Collect будет собирать только то, что может быть собрано ... и, если нагрузка на память высока, алгоритм GC все равно будет делать это чаще, так что редко решение.

Это также показывает, что вы предполагаете, что проблема связана с Stream s = File.Open. Это обернуто в оператор using и сразу после этого выходит из области видимости, это означает, что оно удаляется корректно, а также, вероятно, останется объектом Gen-0, что означает быстрый и эффективный сбор GC.

У вас есть две оставшиеся проблемные области: переменные xxRT, которые вы используете для вызова сохранения в PNG, и акт сохранения трех 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);
    }
...