C# 使用Texture2D.SaveAsPng连续保存多个屏幕截图会导致内存不足异常

C# 使用Texture2D.SaveAsPng连续保存多个屏幕截图会导致内存不足异常,c#,xna,out-of-memory,C#,Xna,Out Of Memory,当我在XNA游戏中进行截图时,每个纹理.SaveAsPng都会消耗一些内存,而且似乎不会返回游戏。所以最终我的内存用完了。我尝试将纹理数据保存到FileStream和MemoryStream,希望可以将其保存为Bitmap,但结果相同。有没有一种方法可以强制释放这个内存,或者有一些解决方法可以让我获取图像数据并以其他方式保存它,而不会出现内存不足异常 sw = GraphicsDevice.Viewport.Width; sh = GraphicsDevice.Viewport.Height;

当我在XNA游戏中进行截图时,每个
纹理.SaveAsPng
都会消耗一些内存,而且似乎不会返回游戏。所以最终我的内存用完了。我尝试将纹理数据保存到
FileStream
MemoryStream
,希望可以将其保存为
Bitmap
,但结果相同。有没有一种方法可以强制释放这个内存,或者有一些解决方法可以让我获取图像数据并以其他方式保存它,而不会出现内存不足异常

sw = GraphicsDevice.Viewport.Width;
sh = GraphicsDevice.Viewport.Height;

int[] backBuffer = new int[sw * sh];
GraphicsDevice.GetBackBufferData(backBuffer);
using(Texture2D texture = new Texture2D(GraphicsDevice, sw, sh, false,
  GraphicsDevice.PresentationParameters.BackBufferFormat))
{
    texture.SetData(backBuffer);
    using(var fs = new FileStream("screenshot.png", FileMode.Create))        
        texture.SaveAsPng(fs, sw, sh);  // ← this line causes memory leak      
}

您可以直接从纹理字节创建位图,并绕过内部方法来检查
SaveAsPng
是否泄漏或其他内容

尝试这种扩展方法(不幸的是,我无法测试(没有xna在工作),但它应该可以工作。)

以上代码应为最后手段


祝你好运。

你能发布一个产生“内存泄漏”的小例子吗?你能显示保存纹理的代码吗?纹理是否
Texture2D
?我直接尝试了GC方法,但不幸的是没有成功。然后我用你的代码制作了108个屏幕截图,虽然花费了相当长的时间,但每4096×4096个图像的消耗量从未超过800兆字节。谢谢!谢谢你,这工作太完美了。SaveAsPng内存泄漏正在扼杀我的项目
public static class TextureExtensions
{
    public static void TextureToPng(this Texture2D texture, int width, int height, ImageFormat imageFormat, string filename)
    {
        using (Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb))
        {
            byte blue;
            IntPtr safePtr;
            BitmapData bitmapData;
            Rectangle rect = new Rectangle(0, 0, width, height);
            byte[] textureData = new byte[4 * width * height];

            texture.GetData<byte>(textureData);
            for (int i = 0; i < textureData.Length; i += 4)
            {
                blue = textureData[i];
                textureData[i] = textureData[i + 2];
                textureData[i + 2] = blue;
            }
            bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            safePtr = bitmapData.Scan0;
            Marshal.Copy(textureData, 0, safePtr, textureData.Length);
            bitmap.UnlockBits(bitmapData);
            bitmap.Save(filename, imageFormat);
        }
    }
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();