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

- 16,982
- 6
- 61
- 79

- 7,033
- 14
- 43
- 71
-
1You may want to read this https://social.msdn.microsoft.com/Forums/en-US/accf4254-ee81-4059-9251-619bc6bbeadf/clear-a-concurrentqueue?forum=rx – Akira Yamamoto Dec 10 '14 at 17:08
-
For anyone stumbling on this article - Clear() was added in .NET Core 2.0 https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentbag-1.clear?view=net-6.0 – Jon R Nov 04 '22 at 17:26
7 Answers
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:
reference assignment is atomic so why is Interlocked.Exchange(ref Object, Object) needed?
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 :-)

- 1
- 1

- 63,413
- 11
- 150
- 187
-
Wouldn't a better solution to be to just take a copy of the bag's reference any place you consume the bag, then you can merely do `bag = new` with impunity? – Chris Marisic Feb 12 '15 at 17:38
-
1@ChrisMarisic Yes, if you can avoid sharing data at all then you are free of these issues. The question didn't have much context, however. – Adam Houldsworth Feb 13 '15 at 08:08
-
11
-
5How does `Interlocked.Exchange` work if another thread is adding to the bag at the time of the exchange? Does that `Add` get locked during the `Exchange`? – Brandon Oct 09 '15 at 14:13
-
3Assigments are atomic in .NET, both the lock and `Interlocked.Exchange` are redundant here (and provide no thread safety). – Lou Mar 10 '17 at 09:19
-
@Lou Good shout, but is the construction of the object atomic or could two threads race to create `ConcurrentBag` and the last one wins on the assignment? In this case I guess it's actually pretty inconsequential at any rate. – Adam Houldsworth Mar 10 '17 at 09:25
-
@Adam: well, the only difference it would make if somehow the `ConcurrentBag` constructor was mutating shared state, which would be a code smell for any constructor whatsoever. Removing synchronization will give you better throughput, i.e. less contention, so it doesn't matter if GC collects the second instance immediately. In both cases, you won't be able to control if a different thread is adding an item to the new collection, or already added it to the previous one. – Lou Mar 10 '17 at 10:03
Although it might not completely clear due to a potential race condition, this is sufficient:
while (!myBag.IsEmpty)
{
myBag.TryTake(out T _);
}

- 187,200
- 47
- 362
- 445
-
25This is definitely not atomic. So should not be added as an extension method on ConcurrentBag I guess, as all the other methods are used with the assumption of atomic access. – Anupam Sep 04 '13 at 01:18
-
Also, can't TryTake fail for other reasons besides it being empty? – BrainSlugs83 Sep 10 '14 at 05:42
-
24This is very dangerous.If another process is adding items continously this could remain busy. – IvoTops Oct 06 '14 at 13:23
-
-
4
-
1if this is a dangerous solution, why is it still accepted answer? – Barış Akkurt Jun 27 '19 at 08:27
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.
-
2There are a lot of other important differences between he collections though. For example, if you need to determine if a given item is in the collection it's both trivial and efficient with a Bag, but not with a Stack. – Servy Jun 26 '13 at 18:18
-
1@Servy: Yeah but still. No, actually, I did start writing a pro/con list, but it really depends on what your requirements are. For instance, concurrent collections are good for multithreaded access, but none of them allow you to index into the collection, something that may prevent you from using them. The question was specifically about clearing a concurrent bag (which is why I came across it), and trivial clearing of the collection with thread safety was my requirement. My answer was to switch collections. – Jun 26 '13 at 18:38
-
2I also use concurrent stack instead of bag. It is strange that stack has Clear and Bag not. Main purpose of bag is to store values, check existence and remove all or single. So concurrent stack becomes something similar to "a bit limited real concurrent bag". – Maxim Jun 24 '14 at 18:15
-
1@Servy how can you determine efficiently if a given item is contained in a `ConcurrentBag`? I can't see any native property or method for doing that. The `Contains` doesn't count. It is an extension method for generic `IEnumerable`s, and it is anything but efficient. – Theodor Zoulias Oct 29 '20 at 12:44
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.

- 49,934
- 160
- 51
- 83

- 1,232
- 1
- 16
- 27
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.

- 1,263
- 14
- 16
-
Nice one! This should be considered as the container type chosen for such instances. ConcurrentStack similarly. – Latency Aug 26 '20 at 18:36
Well, I always think its better to let the underlying framework do the work. I simply wrap the logic inside a dedicated function, post the function call, all local variables will automatically be discarded as and when GC feels necessary.
void MyMainFunction(){
DoWorkWithTheBag();
}
void DoWorkWithTheBag(){
var newBag = new ConcurrentBag();
.....
}
You could also call GC.Collect if you wish to force the GC.

- 99
- 5
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.

- 11