简体   繁体   中英

foreach throws NullReferenceException on ObservableCollection

I have class ElementRelation { ... } and class ElementRelationCollection : System.Collections.ObjectModel.ObservableCollection<ElementRelation> { ... }

And I have this code:

ElementRelationCollection a = ...;
if (a == null)
    throw new Exception("a is null(???)"); // this exception is never thrown
try
{
    foreach (ElementRelation relation in a) // exception is thrown here
    { ... } // never thrown here
}
catch (NullReferenceException ex)
{
    string message = "Something is null here. a.Count: " + a.Count;
    IEnumerator<ElementRelation> enumerator = a.GetEnumerator();
    message += ", enumerator is " + (enumerator == null ? "null" : "not null");
    throw new Exception(message, ex);
}

I can see from the logs that this code sometimes throws an Exception with message "Something is null here. a.Count: 9, enumerator is not null". When this starts happening it continues top happen on every page load until I iisreset.

The innerexception of course is a System.NullReferenceException and it has this stacktrace:

at MyNamespace.MyClass.MyMethod() in c:\path\MyClass.cs:line 74

where line 74 is the line that says foreach (ElementRelation relation in a)

Why does it throw this exception?

Edit:

The collection is sometimes updated by a background thread. I thought this could not cause worse problems than a failed iteration but it turns out the whole collection becomes corrupted.

The ObservableCollection<T> class is not thread-safe. Modifying it from multiple threads can corrupt the internal state to such an extent that it becomes impossible to modify or enumerate the instance.

You will randomly see exceptions such as NullReferenceException and IndexOutOfRangeException - and that's the best possible result! In other cases, the changes to the collection could be silently dropped.

You will either need to wrap your access to the list in a lock, possibly using the ReaderWriterLockSlim class , or switch to a thread-safe collection. For .NET 4.0, the System.Collections.Concurrent namespace has several possibilities.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM