How to remove all Items from ConcurrentBag?

C#Concurrency

C# Problem Overview


How to clear the ConcurrentBag? it don't have any method like Clear or RemoveAll...

C# Solutions


Solution 1 - C#

Update 10/03/2017: As @Lou correctly points out, assignment is atomic. In this instance, creation of the ConcurrentBag will not be atomic, but putting that reference into the variable will be atomic - so locking or Interlocked.Exchange around it is not strictly required.

Some further reading:

https://stackoverflow.com/questions/2192124/reference-assignment-is-atomic-so-why-is-interlocked-exchangeref-object-object

https://stackoverflow.com/questions/5209623/is-a-reference-assignment-threadsafe


You could always lock access to the bag itself and create a new instance of it. Items in the bag will then be elligible for GC if nothing else is holding onto them:

lock (something)
{
    bag = new ConcurrentBag();
}

Or as Lukazoid points out:

var newBag = new ConcurrentBag();
Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);

Easy way to bin the contents, however, this assumes that whenever an item wants access it also gets the lock - this could be expensive and might negate the performance tuning that has gone into the ConcurrentBag itself.

If you know that nothing else will access the bag at this time, wing-and-a-prayer it and don't lock :-)

Solution 2 - C#

Although it might not completely clear due to a potential race condition, this is sufficient:

while (!myBag.IsEmpty) 
{
   myBag.TryTake(out T _);
}

Solution 3 - C#

The selected answer is kind of, well, a workaround, so I'm adding my own workaround.

My solution was to look at all the available collections in the System.Collections.Concurrent namespace to find one where it was trivial to clear all elements from the collection.

The ConcurrentStack class has a Clear() method which removes all elements from the collection. In fact, it's the only collection in the namespace (currently) that does. Yes, you have to Push(T element) instead of Add(T element), but frankly that's worth the time saved.

Solution 4 - C#

As of .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0, there is a Clear() method on ConcurrentBag<T>. See: ConcurrentBag.Clear.

Solution 5 - C#

In the spirit of workarounds.. ConcurrentDictionary<T, bool> has an atomic Clear, but also allows you to quickly check if a key exists. 'Quickly' is a relative term of course, but depending on your usage it might be faster than enumerating a large stack.

Solution 6 - C#

int cnt = _queue.Count;
for (; cnt > 0; cnt--)
{
     _queue.TryDequeue(out img);
}

It does not fall into an infinite loop, and clears the contents of the present time.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPawanSView Question on Stackoverflow
Solution 1 - C#Adam HouldsworthView Answer on Stackoverflow
Solution 2 - C#Daniel A. WhiteView Answer on Stackoverflow
Solution 3 - C#user1228View Answer on Stackoverflow
Solution 4 - C#olabackerView Answer on Stackoverflow
Solution 5 - C#OlduwanSteveView Answer on Stackoverflow
Solution 6 - C#a_pcnicView Answer on Stackoverflow