简体   繁体   English

foreach在ObservableCollection上引发NullReferenceException

[英]foreach throws NullReferenceException on ObservableCollection

I have class ElementRelation { ... } and class ElementRelationCollection : System.Collections.ObjectModel.ObservableCollection<ElementRelation> { ... } 我有class ElementRelation { ... } class ElementRelationCollection : System.Collections.ObjectModel.ObservableCollection<ElementRelation> { ... }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". 我从日志中看到,此代码有时会引发异常,并显示消息“这里的东西为空。a.Count:9,枚举数不为空”。 When this starts happening it continues top happen on every page load until I iisreset. 当这种情况开始发生时,它会继续在每个页面加载上排在最前面,直到iisreset。

The innerexception of course is a System.NullReferenceException and it has this stacktrace: 内部异常当然是System.NullReferenceException,它具有以下堆栈跟踪:

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

where line 74 is the line that says foreach (ElementRelation relation in a) 其中第74行是说foreach (ElementRelation relation in a)的行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. ObservableCollection<T>类不是线程安全的。 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! 你会随机看到的例外,如NullReferenceExceptionIndexOutOfRangeException -这是最好的可能的结果! 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. 您可能需要使用ReaderWriterLockSlim将您对列表的访问权包装在一个锁中,或者切换到线程安全的集合。 For .NET 4.0, the System.Collections.Concurrent namespace has several possibilities. 对于.NET 4.0, System.Collections.Concurrent命名空间具有多种可能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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