BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Parallel and Asynchronous
.NET 4.0+

Thread-Safe Stacks with ConcurrentStack<T>

.NET 4.0 introduced several thread-safe collection types that can be used in parallel code without manual thread synchronisation. The ConcurrentStack<T> class is one such collection. It allows the creation of thread-safe, last-in, first-out stacks.

Range Methods

Sometimes you'll need to work with batches of items. If it's important that groups of items remain together in the stack you need to make sure that another thread or parallel task does not push other items into the collection at the same time. This would cause batches to become interspersed. The problem is solved with the use of the PushRange method.

PushRange has two overloads. The simpler accepts an array of items. Each item in the array is pushed onto the concurrent stack in turn. During the process, all other threads that attempt to change the stack are blocked. The second overload adds two integer parameters. These specify a starting index in the array and the number of items to add to the stack, allowing you to push a contiguous subset of items from the source array.

The code below shows an example usage of the basic version of PushRange. This pushes the values 1, 2 and 3 onto a stack of integers.

var stack = new ConcurrentStack<int>();
int[] values = new int[] { 1, 2, 3 };
stack.PushRange(values);

If you need to push items onto a stack in groups, it's likely you'll also wish to pop them in a similar manner. For this you can use TryPopRange. Again there are two overloaded versions. The simpler requires an array to be provided as its only argument. This array is populated with any items that can be popped off the stack. The size of the array determines the maximum number of items that may be popped. If fewer items are available, only the first part of the array will be filled. If the array is too small to empty the collection, the excess items will remain in the stack. In any case, the return value is an integer that holds the number of items retrieved.

The second overload allows the addition of a starting index and number of items. When used, only the specified section of the array will be populated with popped items.

The following code pushes three items onto the stack and pops them into an array with five elements. The final result is that the first three elements of the array receive the items from the stack in LIFO order. The last two array elements are unaffected and the return value indicates that three items were retrieved.

var stack = new ConcurrentStack<int>();
int[] values = new int[] { 1, 2, 3 };
stack.PushRange(values);

int[] popped = new int[5];
int popCount = stack.TryPopRange(popped);

/* RESULTS

popped = { 3, 2, 1, 0, 0 }
popCount = 3

*/
15 June 2013