title: ConcurrentList - Thread safetly not given
body: <p>I have look around a ConcurrentList implementation, and found this one:
  <a href="http://deanchalk.com/2010/10/c-fast-parallel-concurrentlistt-implementation/" rel="nofollow">http://deanchalk.com/2010/10/c-fast-parallel-concurrentlistt-implementation/</a></p>
  
  <p>The code works fine in the implementation you can find on the given webpage, but when I change the the <code>DoWork</code> method:</p>
  
  <p>original:</p>
  
  <pre><code>static void DoWork(ICollection&lt;int&gt; list, int count)
  {
      for (var i = 0; i &lt; count; i++)
      {
          list.Add(i);
          // use spinwait to emulate work but avoiding 
          // context switching
          Thread.SpinWait(100000);
      }
  }
  </code></pre>
  
  <p>changes made:</p>
  
  <pre><code>static void DoWork(ICollection&lt;int&gt; list, int count)
  {
      for (var i = 0; i &lt; count; i++)
      {
          var foo = list.Any(x =&gt; x == 2); //&lt;-- throws exception.. (Enumeration changed)
          if (foo == true)
          {
              //do something...
          }
  
          list.Add(i);
      }
  }
  </code></pre>
  
  <p>This change will break the execution eventually, telling me that the enumeration has been modified.</p>
  
  <p>How can I make this code work?</p>
  
  <p>---- Concurrent List ----</p>
  
  <pre><code>public class ConcurrentList&lt;T&gt; : IList&lt;T&gt;, IList
  {
      private readonly List&lt;T&gt; underlyingList = new List&lt;T&gt;();
      private readonly object syncRoot = new object();
      private readonly ConcurrentQueue&lt;T&gt; underlyingQueue;
      private bool requiresSync;
      private bool isDirty;
  
      public ConcurrentList()
      {
          underlyingQueue = new ConcurrentQueue&lt;T&gt;();
      }
  
      public ConcurrentList(IEnumerable&lt;T&gt; items)
      {
          underlyingQueue = new ConcurrentQueue&lt;T&gt;(items);
      }
  
      private void UpdateLists()
      {
          if (!isDirty)
              return;
          lock (syncRoot)
          {
              requiresSync = true;
              T temp;
              while (underlyingQueue.TryDequeue(out temp))
                  underlyingList.Add(temp);
              requiresSync = false;
          }
      }
  
      public IEnumerator&lt;T&gt; GetEnumerator()
      {
          lock (syncRoot)
          {
              UpdateLists();
              return underlyingList.GetEnumerator();
          }
      }
  
      IEnumerator IEnumerable.GetEnumerator()
      {
          return GetEnumerator();
      }
  
      public void Add(T item)
      {
          if (requiresSync)
              lock (syncRoot)
                  underlyingQueue.Enqueue(item);
          else
              underlyingQueue.Enqueue(item);
          isDirty = true;
      }
  
      public int Add(object value)
      {
          if (requiresSync)
              lock (syncRoot)
                  underlyingQueue.Enqueue((T)value);
          else
              underlyingQueue.Enqueue((T)value);
          isDirty = true;
          lock (syncRoot)
          {
              UpdateLists();
              return underlyingList.IndexOf((T)value);
          }
      }
  
      public bool Contains(object value)
      {
          lock (syncRoot)
          {
              UpdateLists();
              return underlyingList.Contains((T)value);
          }
      }
  
      public int IndexOf(object value)
      {
          lock (syncRoot)
          {
              UpdateLists();
              return underlyingList.IndexOf((T)value);
          }
      }
  
      public void Insert(int index, object value)
      {
          lock (syncRoot)
          {
              UpdateLists();
              underlyingList.Insert(index, (T)value);
          }
      }
  
      public void Remove(object value)
      {
          lock (syncRoot)
          {
              UpdateLists();
              underlyingList.Remove((T)value);
          }
      }
  
      public void RemoveAt(int index)
      {
          lock (syncRoot)
          {
              UpdateLists();
              underlyingList.RemoveAt(index);
          }
      }
  
      T IList&lt;T&gt;.this[int index]
      {
          get
          {
              lock (syncRoot)
              {
                  UpdateLists();
                  return underlyingList[index];
              }
          }
          set
          {
              lock (syncRoot)
              {
                  UpdateLists();
                  underlyingList[index] = value;
              }
          }
      }
  
      object IList.this[int index]
      {
          get { return ((IList)this)[index]; }
          set { ((IList)this)[index] = (T)value; }
      }
  
      public bool IsReadOnly
      {
          get { return false; }
      }
  
      public bool IsFixedSize
      {
          get { return false; }
      }
  
      public void Clear()
      {
          lock (syncRoot)
          {
              UpdateLists();
              underlyingList.Clear();
          }
      }
  
      public bool Contains(T item)
      {
          lock (syncRoot)
          {
              UpdateLists();
              return underlyingList.Contains(item);
          }
      }
  
      public void CopyTo(T[] array, int arrayIndex)
      {
          lock (syncRoot)
          {
              UpdateLists();
              underlyingList.CopyTo(array, arrayIndex);
          }
      }
  
      public bool Remove(T item)
      {
          lock (syncRoot)
          {
              UpdateLists();
              return underlyingList.Remove(item);
          }
      }
  
      public void CopyTo(Array array, int index)
      {
          lock (syncRoot)
          {
              UpdateLists();
              underlyingList.CopyTo((T[])array, index);
          }
      }
  
      public int Count
      {
          get
          {
              lock (syncRoot)
              {
                  UpdateLists();
                  return underlyingList.Count;
              }
          }
      }
  
      public object SyncRoot
      {
          get { return syncRoot; }
      }
  
      public bool IsSynchronized
      {
          get { return true; }
      }
  
      public int IndexOf(T item)
      {
          lock (syncRoot)
          {
              UpdateLists();
              return underlyingList.IndexOf(item);
          }
      }
  
      public void Insert(int index, T item)
      {
          lock (syncRoot)
          {
              UpdateLists();
              underlyingList.Insert(index, item);
          }
      }
  }
  </code></pre>
  
  <p>---- MainWindow.xaml.cs ----</p>
  
  <pre><code>public MainWindow()
  {
      InitializeComponent();
  
      Console.WriteLine(@"standard List&lt;T&lt; - 10000 work items");
      var list1 = new ConcurrentList&lt;int&gt;();
      var start1 = DateTime.Now.Ticks;
      DoWork(list1, 10000);
      var end1 = DateTime.Now.Ticks;
      var c1 = list1.Count; // accesses list
      var cend1 = DateTime.Now.Ticks;
      Console.WriteLine();
      Console.WriteLine(@"Work Time: {0} - milliseconds", (end1 - start1)
          / TimeSpan.TicksPerMillisecond);
      Console.WriteLine(@"Get Count Time: {0} - milliseconds",
          (cend1 - end1)
          / TimeSpan.TicksPerMillisecond);
      Console.WriteLine();
      Console.WriteLine();
  
      Console.WriteLine(@"ConcurrentList&lt;T&gt; - 10000 work items on single thread");
      var list2 = new ConcurrentList&lt;int&gt;();
      var start2 = DateTime.Now.Ticks;
      DoWork(list2, 10000);
      var end2 = DateTime.Now.Ticks;
      var c2 = list2.Count; // accesses list, update performed
      var cend2 = DateTime.Now.Ticks;
      Console.WriteLine();
      Console.WriteLine(@"Work Time: {0} - milliseconds", (end2 - start2)
          / TimeSpan.TicksPerMillisecond);
      Console.WriteLine(@"Get Count Time: {0} - milliseconds",
          (cend2 - end2)
          / TimeSpan.TicksPerMillisecond);
      Console.WriteLine();
      Console.WriteLine();
  
      Console.WriteLine(@"ConcurrentList&lt;T&gt; - 10000 work items on 4 parallel tasks");
      var list3 = new ConcurrentList&lt;int&gt;();
      var start3 = DateTime.Now.Ticks;
      var tasks3 = new[]
          {
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
              Task.Factory.StartNew(() =&gt; DoWork(list3,10000)),
          };
      Task.WaitAll(tasks3);
      var end3 = DateTime.Now.Ticks;
      var c3 = list3.Count; // accesses list, update performed
      var cend3 = DateTime.Now.Ticks;
      Console.WriteLine();
      Console.WriteLine(@"Work Time: {0} - milliseconds", (end3 - start3)
          / TimeSpan.TicksPerMillisecond);
      Console.WriteLine(@"Get Count Time: {0} - milliseconds",
              (cend3 - end3)
          / TimeSpan.TicksPerMillisecond);
      Console.WriteLine();
  }
  
  static void DoWork(ConcurrentList&lt;int&gt; list, int count)
  {
      for (var i = 0; i &lt; count; i++)
      {
          var foo = list.Any(x =&gt; x == 2); //&lt;--- throws Exception (Enumeration changed)
          if (foo)
          {
  
          }
  
          list.Add(Rnd.Next(int.MinValue, int.MaxValue));
  
          // use spinwait to emulate work but avoiding 
          // context switching
          //Thread.SpinWait(100000);
      }
  }
  </code></pre>