0

私は持ってい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);
}

ログから、このコードが「Something is null here. a.Count: 9, enumerator is not null」というメッセージで例外をスローすることがあることがわかります。これが発生し始めると、私がiisresetするまで、ページの読み込みごとにトップが発生し続けます。

もちろん、innerexception は System.NullReferenceException であり、次のスタック トレースがあります。

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

行74は言う行ですforeach (ElementRelation relation in a)

なぜこの例外がスローされるのですか?

編集:

コレクションは、バックグラウンド スレッドによって更新されることがあります。これにより、イテレーションの失敗よりも悪い問題が発生することはないと思っていましたが、コレクション全体が破損していることが判明しました。

4

1 に答える 1

0

ObservableCollection<T>クラスはスレッドセーフではありません。複数のスレッドから変更すると、内部状態が破損し、インスタンスの変更または列挙が不可能になる可能性があります。

NullReferenceExceptionや-などの例外がランダムに表示されますがIndexOutOfRangeException、これが最良の結果です。それ以外の場合は、コレクションへの変更が黙って削除される可能性があります。

おそらくclassを使用ReaderWriterLockSlimて、リストへのアクセスをロックでラップするか、スレッドセーフなコレクションに切り替える必要があります。.NET 4.0 の場合、System.Collections.Concurrent名前空間にはいくつかの可能性があります。

于 2012-11-21T15:53:30.930 に答える