title: Is there a memory leak in the ConcurrentBag<T> implementation?
body: <blockquote>
    <p><strong>Possible Duplicate:</strong><br>
    <a href="https://stackoverflow.com/questions/5353164/possible-memoryleak-in-concurrentbag">Possible memoryleak in ConcurrentBag?</a>  </p>
  </blockquote>
  
  
  
  <p>Edit1:</p>
  
  <p>The actual question is. Can you confirm this or is my sample wrong and I am missing somthing obvious?</p>
  
  <p>I have thought that ConcurrentBag is simpy a replacement for an unorderd list. But I was wrong. ConcurrentBag does add itself to as ThreadLocal to the creating thread which does basically cause a memory leak.</p>
  
  <pre><code>   class Program
      {
          static void Main(string[] args)
          {
              var start = GC.GetTotalMemory(true);
              new Program().Start(args);
              Console.WriteLine("Diff: {0:N0} bytes", GC.GetTotalMemory(true) - start);
              GC.Collect();
              GC.WaitForPendingFinalizers();
              GC.Collect();
              Thread.Sleep(5000);
          }
  
          private void Start(string[] args)
          {
              for (int i = 0; i &lt; 1000; i++)
              { 
                  var bag = new ConcurrentBag&lt;byte&gt;();
                  bag.Add(1);
                  byte by;
                  while (bag.TryTake(out by)) ;
              }
          }
  </code></pre>
  
  <p>I can make Diff 250 KB or 100 GB depending on how much data I add to the bags. The data nor the bags go away.</p>
  
  <p>When I break into this with Windbg and I do a 
  !DumpHeap -type Concurrent </p>
  
  <p>....</p>
  
  <pre><code>000007ff00046858        1           24 System.Threading.ThreadLocal`1+GenericHolder`3[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System],[System.Threading.ThreadLocal`1+C0[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]], mscorlib],[System.Threading.ThreadLocal`1+C0[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]], mscorlib],[System.Threading.ThreadLocal`1+C0[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]], mscorlib]]
  000007feed812648        2           64 System.Collections.Concurrent.ConcurrentStack`1[[System.Int32, mscorlib]]
  000007feece41528        1          112 System.Collections.Concurrent.CDSCollectionETWBCLProvider
  000007ff000469e0     1000        32000 System.Threading.ThreadLocal`1+Boxed[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]]
  000007feed815900     1000        32000 System.Collections.Concurrent.ConcurrentStack`1+Node[[System.Int32, mscorlib]]
  000007ff00045530     1000        72000 System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]]
  </code></pre>
  
  <p>When I do create an empty ConcurrentBag to let some worker threads add data to it ConcurrentBag and its data will be there as long as the creating thread is still alive. </p>
  
  <p>This way I got a several GB memory leak. I did "fix" this by using a List and locks. ConcurrentBag may be fast but it is useless as simple replacement for a List with the same object lifetime. </p>
  
  <p>If I ever create a ConcurrentBag on the main thread I will keep it as long as the thread is alive. This is not something I would expect and it can cause major pain. </p>