I have a static list of WeakReference's in my application. At some point, I want to take a snapshot of all the currently "alive" objects in this list.
Code is like this:
private static readonly List<WeakReference> myObjects = new List<WeakReference>();
public static MyObject[] CollectObjects()
{
var list = new List<MyObject>();
foreach (var item in myObjects)
{
if (!item.IsAlive)
continue;
var obj = item.Target as MyObject;
list.Add(obj);
}
return list.ToArray();
}
The problem I'm having is that I sometimes (rarely) get a "Collection Was Modified" exception in the foreach loop above. I only add/remove from this list in the MyObject constructor/finalizers, which looks like this:
public class MyObject
{
private static readonly object _lockObject = new object();
WeakReference referenceToThis;
public MyObject()
{
lock (_lockObject)
{
referenceToThis = new WeakReference(this);
myObjects.Add(referenceToThis);
}
}
~MyObject()
{
lock (_lockObject)
{
myObjects.Remove(referenceToThis);
}
}
}
Since nothing else in my code is touching the list, my assumption is therefore that the garbage collector is finalizing some of those objects just as I try to enumerate the list.
I thought about adding a lock (_lockObject)
around the foreach loop but I'm not sure how such a lock would affect the GC?
Is there a better/correct/safer way to enumerate over a List of WeakReferences?