Hi,
I got a strange exception sometime when I try to dispose a RenderTarget2D
it’s happen about 1 in 30 times and I do not understand what is wrong here.
Project:
Windows/OpenGL/Monogame 3.5.1
Declaration:
_target = new RenderTarget2D(graphicsDevice, Width, Height, false, SurfaceFormat.Color, graphicsDevice.PresentationParameters.DepthStencilFormat, graphicsDevice.PresentationParameters.MultiSampleCount, RenderTargetUsage.PreserveContents);
Exception:
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
StackTrace:
System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) à System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator.MoveNext() à Microsoft.Xna.Framework.Graphics.GraphicsDevice.PlatformDeleteRenderTarget(Texture renderTarget) à Microsoft.Xna.Framework.Graphics.RenderTarget2D.<Dispose>b__c() à Microsoft.Xna.Framework.Threading.BlockOnUIThread(Action action) à Microsoft.Xna.Framework.Graphics.RenderTarget2D.Dispose(Boolean disposing) à Microsoft.Xna.Framework.Graphics.GraphicsResource.Finalize()
The code that throws the exception is GraphicsDevice.OpenGL.cs (Monogame 3.5.1 Source):
internal void PlatformDeleteRenderTarget(Texture renderTarget) { var color = 0; var depth = 0; var stencil = 0; var colorIsRenderbuffer = false;
var renderTarget2D = renderTarget as RenderTarget2D; if (renderTarget2D != null) { color = renderTarget2D.glColorBuffer; depth = renderTarget2D.glDepthBuffer; stencil = renderTarget2D.glStencilBuffer; colorIsRenderbuffer = color != renderTarget2D.glTexture; }
if (color != 0) { if (colorIsRenderbuffer) this.framebufferHelper.DeleteRenderbuffer(color); if (stencil != 0 && stencil != depth) this.framebufferHelper.DeleteRenderbuffer(stencil); if (depth != 0) this.framebufferHelper.DeleteRenderbuffer(depth);
var bindingsToDelete = new List<RenderTargetBinding[]>(); foreach (var bindings in this.glFramebuffers.Keys) { foreach (var binding in bindings) { if (binding.RenderTarget == renderTarget) { bindingsToDelete.Add(bindings); break; } } }
foreach (var bindings in bindingsToDelete) { var fbo = 0; if (this.glFramebuffers.TryGetValue(bindings, out fbo)) { this.framebufferHelper.DeleteFramebuffer(fbo); this.glFramebuffers.Remove(bindings); } if (this.glResolveFramebuffers.TryGetValue(bindings, out fbo)) { this.framebufferHelper.DeleteFramebuffer(fbo); this.glResolveFramebuffers.Remove(bindings); } } } }
I am sure the RenderTarget is not use after Disposing, so… I don’t understand why one of the foreach loops crash.