What do you mean with fail?
Take the following example:
var queue = new Queue<string>();
string temp = queue.Dequeue();
// do something with temp
The above code with throw an exception, since we try to dequeue from an empty queue. Now, if you use a ConcurrentQueue<T>
instead:
var queue = new ConcurrentQueue<string>();
string temp;
if (queue.TryDequeue(out temp))
{
// do something with temp
}
The above code will not throw an exception. The queue will still fail to dequeue an item, but the code will not fail in the way of throwing an exception. The real use for this becomes apparent in a multithreaded environment. Code for the non-concurrent Queue<T>
would typically look something like this:
lock (queueLock)
{
if (queue.Count > 0)
{
string temp = queue.Dequeue();
// do something with temp
}
}
In order to avoid race conditions, we need to use a lock to ensure that nothing happens with the queue in the time that passes from checking Count
do calling Dequeue
. With ConcurrentQueue<T>
, we don't really need to check Count
, but can instead call TryDequeue
.
If you examine the types found in the Systems.Collections.Concurrent
namespace you will find that many of them wrap two operations that are typically called sequentially, and that would traditionally require locking (Count
followed by Dequeue
in ConcurrentQueue<T>
, GetOrAdd
in ConcurrentDictionary<TKey, TValue>
replaces sequences of calling ContainsKey
, adding an item and getting it, and so on).