我有class ElementRelation { ... }
和class ElementRelationCollection : System.Collections.ObjectModel.ObservableCollection<ElementRelation> { ... }
我有这段代码:
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);
}
我可以从日志中看到,这段代码有时会抛出带有消息的Exception “这里的东西是空的.a.Count:9,枚举器不为空”。当这种情况开始发生时,它会继续在每个页面加载时发生,直到我iisreset。
当然,innerexception是一个System.NullReferenceException,它有这个堆栈跟踪:
at MyNamespace.MyClass.MyMethod() in c:\path\MyClass.cs:line 74
其中第74行是foreach (ElementRelation relation in a)
为什么会抛出此异常?
修改
该集合有时由后台线程更新。我认为这不会导致比迭代失败更严重的问题,但事实证明整个集合都已损坏。
答案 0 :(得分:0)
ObservableCollection<T>
类不是线程安全的。从多个线程修改它可能会破坏内部状态,使得无法修改或枚举实例。
您将随机查看NullReferenceException
和IndexOutOfRangeException
等异常,这是最好的结果!在其他情况下,可以静默删除对集合的更改。
您可能需要在锁中包含对列表的访问权限,可能使用the ReaderWriterLockSlim
class,或切换到线程安全的集合。对于.NET 4.0,System.Collections.Concurrent
namespace有几种可能性。