2

ジェネリック ディクショナリ (WinRT C#) に値を追加しているときに、IndexOutOfRange 例外が発生します。以下は私のコードと例外のスタックトレースです。

コード:

if (!data.TryGetValue(index, out cells))
{
   cells = new CellCollection();
   data.Add(index, cells);
}

スタックトレース:

System.Collections.Generic.Dictionary 2.Insert(TKey key, TValue value, Boolean add) at System.Collections.Generic.Dictionary2.Add (TKey キー、TValue 値) で

追加中にこの範囲外の例外が発生するとは思わないでしょう。私のアプリケーションはシングル スレッドのみを使用します。辞書に値を追加し、不要な場合は GC.Collect() を使用して辞書から削除します。そして、必要に応じて値を追加します。

この例外を解決するための提案を誰でもできますか?

4

1 に答える 1

4

の呼び出し中に、が の現在の容量を超えるDictionary<,>.Addため、新しいバッキング アレイを割り当てる必要がある場合があります。新しいマネージド オブジェクト (新しい配列) を割り当てるときに、ガベージ コレクターが設定される場合があります。アプリケーションは「一時停止」され、ガベージ コレクションが行われます。次に、ガベージが収集された後、メソッド内にあった場所から制御が再開され、新しいバッキング配列が古いバッキング配列からのデータで満たされます。CountDictionary<,>Add

ただし、上記の質問に対するコメントに基づいて、ファイナライザーがあります。ファイナライズ中の無関係なオブジェクト (同じクラスの別のインスタンスなど) が存在する必要があります。同じへの参照を保持しているようDictionary<,>です。ファイナライズ中、デストラクタ コードで、Dictionary<,>. その後、ガベージ コレクション後にメイン スレッドが制御を再開すると、 の状態はDictionary<,>変更されていますが、その に 1 つの新しい要素を追加するプロセスの途中でしたDictionary<,>

教訓は次のとおりです。デストラクタ (ファイナライザ) を記述しないでください。いずれにせよ、他の場所から参照される (つまり、収集されない「生きている」オブジェクトから参照される可能性がある) 管理対象オブジェクトの状態を変更しないでください。

マシュー・ワトソンはあなたの質問へのコメントでそれを言った.

于 2014-11-05T09:47:12.853 に答える