2

私の友人のコードでは、彼はList

 List<int> listOfIds = new List<int>();

次にAddRange()、intのコレクションを追加していました。

   listOfIds.AddRange(this._employeeList
                       .Where(r => r.EmployeeID != null)
                       .Select(r => r.EmployeeID != null ? r.EmployeeID.Value : 0));

しかし、その後、ログには次のように書かれています。

 System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Collections.Generic.List`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
   at the method which called the codes above.....

なぜこれが起こったのかよくわかりません。このエラーは上記のコードで発生したと確信していますが、なぜ発生するのか理解できないようですIndexOutofRangeException

これを引き起こす可能性のあるものを指摘するのを手伝ってもらえますか?

アップデート:

私は間違っています。大変申し訳ございません。このメソッドはマルチスレッドを使用しません。しかし、このメソッドを呼び出した別のメソッドは、マルチスレッドを意味するParallel.Foreachを使用しています。_employeeListがAddRange()のソースとして使用されているときに、別のスレッドもそれを変更している可能性があります。したがって、addrange()がスレッドセーフではないという答えはもっともらしいです。どうもありがとうございました。

4

1 に答える 1

2

より具体的なアイデアを伝えるのは難しいですが、これはうまくいくかもしれません。

AddRangeスレッドセーフではありません。lock primitives多くのアイテムを追加するために使用してみてください。宣言する:

private static object mutex = new object();

使用法

lock(mutex)
{
    listOfIds.AddRange( /* code goes here */ )
}

AddRange見つかったの逆コンパイル後

public void AddRange(IEnumerable<T> collection)
{
  this.InsertRange(this._size, collection);
}

InsertRangeスタックトレースで確認できるの内容:

  ...
  ICollection<T> collection1 = collection as ICollection<T>;
  if (collection1 != null)
  {
     ...
  }
  else
  {
    foreach (T obj in collection)
      this.Insert(index++, obj);
  }

言い換えると、シーケンスを繰り返し、インクリメントされたインデックスを使用してアイテムごとに追加しようとします。これは間違いないはずですよね?によって逆コンパイルされた845行。したがって、スタックトレース全体が表示される場合を除いて、スタックトレースは信頼できません。List.csdotPeek

于 2013-01-10T15:13:10.237 に答える