ConcurrentStack
is the thread safe counterpart of Systems.Collections.Generic.Stack
, which is the standard Last-In-First-Out (LIFO) container in the .NET Framework. For algorithms that favor stack usage such as depth-first searches, a thread safe stack is a big benefit.
In this recipe we are going to take a look at the basic usage of ConcurrentStack
. Our Console
application for this recipe will initialize a range of data, which a simple producer Task
will push onto the stack. Consumer Task
will concurrently pop items from the stack and write them to Console
.
Now, let's take a look at performing LIFO operations with ConcurrentStack
.
ConcurrentStack
as the Solution name.using
directives to the top of your Program
class:using System; using System.Collections.Concurrent; using System.Linq; using System.Threading; using System.Threading.Tasks;
Main
method of the Program
class, let's create our range of input data and our blocking collection.var data = Enumerable.Range(0, 100); ConcurrentStack<int> stack = new ConcurrentStack<int>();
for
loop to iterate through the numbers of our source data and pop them onto the stack.// producer Task.Factory.StartNew(() => { foreach (var item in data) { stack.Push(item); Console.WriteLine("Pushing item onto stack:{0} Item Count={1}", item, stack.Count); } });
Task
which will use a while
loop to pop items off the stack while the IsEmpty
property of the stack is false. Finish by waiting for user input before exiting.//consumer Task.Factory.StartNew(() => { Thread.SpinWait(1000000); while (!stack.IsEmpty) { int result = 0; stack.TryPop(out result); Console.WriteLine("Popping item from stack:{0} Item Count={1}", result, stack.Count); } }); Console.ReadLine();
ConcurrentStack
achieves thread safe access by using the System.Threading.Interlocked
operations. Interlocked operations provide a simple mechanism for synchronizing access to variables shared by multiple threads. Interlocked operations are also very fast.
For the most part, ConcurrentStack
behaves like System.Collections.Generic.Stack
. To push an item onto the stack, you just use the Push
method.
foreach (var item in data) { stack.Push(item); Console.WriteLine("Pushing item onto stack:{0} Item Count={1}", item, stack.Count); }
However, the Pop
method was removed in favor of TryPop
. TryPop
returns true
if an item existed and was popped, otherwise it returns false
. The out
parameter contains the object removed if the pop was successful, otherwise it is indeterminate.
while (!stack.IsEmpty) { int result = 0; stack.TryPop(out result); Console.WriteLine("Popping item from stack:{0} Item Count={1}", result, stack.Count); }
3.143.3.104