title: Take all items from ConcurrentBag using a swap
body: <p>I'm trying to take all items in one fell swoop from a <code>ConcurrentBag</code>. Since there's nothing like <code>TryEmpty</code> on the collection, I've resorted to using <code>Interlocked.Exchange</code> in the same fashion as described here: <a href="https://stackoverflow.com/questions/5377296/how-to-remove-all-items-from-concurrentbag">How to remove all Items from ConcurrentBag?</a></p>
  
  <p>My code looks like this:</p>
  
  <pre><code>private ConcurrentBag&lt;Foo&gt; _allFoos; //Initialized in constructor.
  
  public bool LotsOfThreadsAccessingThisMethod(Foo toInsert)
  {
      this._allFoos.Add(toInsert);
      return true;
  }
  
  public void SingleThreadProcessingLoopAsALongRunningTask(object state)
  {
      var token = (CancellationToken) state;
      var workingSet = new List&lt;Foo&gt;();
  
      while (!token.IsCancellationRequested)
      {
          if (!workingSet.Any())
          {
              workingSet = Interlocked.Exchange(ref this._allFoos, new ConcurrentBag&lt;Foo&gt;).ToList();
          }
  
          var processingCount = (int)Math.Min(workingSet.Count, TRANSACTION_LIMIT);
  
          if (processingCount &gt; 0)
          {
              using (var ctx = new MyEntityFrameworkContext())
              {
                  ctx.BulkInsert(workingSet.Take(processingCount));
              }
              workingSet.RemoveRange(0, processingCount);
          }
      }
  }
  </code></pre>
  
  <p>The problem is that this sometimes misses items that are added to the list. I've written a test application that feeds data to my <code>ConcurrentBag.Add</code> method and verified that it is sending all of the data. When I set a breakpoint on the <code>Add</code> call and check the count of the <code>ConcurrentBag</code> after, it's zero. The item just isn't being added. </p>
  
  <p>I'm fairly positive that it's because the <code>Interlocked.Exchange</code> call doesn't use the internal locking mechanism of the <code>ConcurrentBag</code> so it's losing data somewhere in the swap, but I have no knowledge of what's actually happening.</p>
  
  <p>How can I just grab all the items out of the <code>ConcurrentBag</code> at one time without resorting to my own locking mechanism? And why does <code>Add</code> ignore the item?</p>