问题
I'm using SaveAsPng() on a RenderTarget2D object every frame. I dispose of both the RenderTarget2D and the input stream on every frame too. Yet, just before about 500 images saved I get a message saying the application ran out of memory.
I tried changing around when I call Dispose(), but I got the same result every time.
RenderTarget2D rt;
protected override void Update(GameTime gameTime)
{
if (rt != null)
{
rt.Dispose();
}
rt = new RenderTarget2D(GraphicsDevice, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
GraphicsDevice.SetRenderTarget(rt);
GraphicsDevice.Clear(Color.Transparent);
sb.Begin();
//I draw stuff here.
sb.End();
GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Clear(Color.Black);
Stream stream = File.Create(path);
rt.SaveAsPng(stream, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
stream.Dispose();
stream.Close();
}
What I expect this to do is release the memory associated with the picture drawn on the previous frame, assign new memory space to the new RenderTarget2D and as such, only use as much memory as to store a single one of the images I'm drawing. For some reason, I think, all the images are stored in memory until space runs out. (The error is generated by the SaveAsPng method call, memory usage seems to go up linearly with run time according to VS and nothing in the application, other than this little image processing bit uses large chunks of memory.)
Update: This is my first time ever using memory snapshots, so I must be looking at this wrong, but to me it looks like the data on the left doesn't seem to reflect the memory usage graph on the right.
Snapshot Comparison
回答1:
It is very hard to figure out without profiling. Try to take memory snapshots using visual studio and identify the places where the memory gets build up.
https://docs.microsoft.com/en-us/visualstudio/profiling/memory-usage?view=vs-2019
回答2:
I have a couple of thoughts.
First, it's recommended to use the using
construct with File.Create
, since that does the clean up for you (see the examples here) Something like:
using (Stream stream = File.Create(path)) {
rt.SaveAsPng(stream, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
}
That'll ensure that the stream is disposed of correctly.
My next thought is that Update()
is called very frequently, so you might be overwhelming the garbage collector. Since the images are going to be relatively large, perhaps C# simply isn't freeing up the memory in time.
Maybe you should limit the rate at which images are saved (maybe every 0.5 seconds).Then it'll be more obvious if you're leaking memory somehow or just overwhelming the garbage collector.
Hope that helps.
来源:https://stackoverflow.com/questions/57066281/application-runs-out-of-memory-while-saving-textures-to-png-files