We are currently working on switching levels in our game. We use a contentmanager for the gamescreen, which should be unloaded when a new level is loaded. After several level changes, we receive a low memory crash.
I have noticed that the destructors of the types we loaded using the content.load were not called and the levels were not unloaded properly. This does not happen in XNA on Windows or WP, but happens on my iPad.
Calling Content.Unload manually helps, but it is just a workaround.
How are you destructing the ContentManager? Are you just waiting for the finalizer to fire?
Looking at the code...
... looks like the finalizer is doing Dispose(false) which keeps it from calling Unload(). Seems like we should just put Unload() in the finalizer.
Yep, we get rid of all the references and call GC.Collect().
This seems the be the issue:
private static List ContentManagers = new List();
That's wrong. We have a game that is unloading fine both on Windows 7 and WP7 without calling dispose.
We should just let the garbage collector do the job (why should I take out the trash myself if the trashman comes to my house?). Currently, MonoGame does not let the GC do its job.
I see that it was added for Android, but in my opinion, the way the whole thing is handled is plain wrong.
If you do this, then you need to make sure that you check the value of 'target' in the WeakReference for unexpected nulls. the GC will collect your object as it sees fit when you use the WeakReference. Be wary. I've used this on large collections with unexpected results. The "WeakReference" object is not collected, only its target...
@slygamer It is called IDisposABLE, not IMustBeDisposed.
From MSDN: "The primary use of this interface is to release unmanaged resources. The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used. However, it is not possible to predict when garbage collection will occur. Furthermore, the garbage collector has no knowledge of unmanaged resources such as window handles, or open files and streams."
So resources will be released by the GC anyway, but we don't know when (there are no unmanaged resources in ContentManager). That's why we call GC.Collect() after unreferencing.
I like the idea of WeakReferences. It should allow us to reuse ContentManagers via Unload().
See the first answer here regarding the proper use of IDisposable:
We should never rely on the user calling Dispose.
I will rewrite this later today.
ContentManager uses WeakReference for list
Change ContentManager's internal list of content managers to a list of WeakReference so content managers can be freed by game code releasing all references to them. Fixes issue #848.