ConcurrentStack<T>
Class
Definition
Represents a thread-safe last in-first out (LIFO) collection.
public class ConcurrentStack<T> : System.Collections.Concurrent.IProducerConsumerCollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>
- T
The type of the elements contained in the stack.
- Inheritance
-
ConcurrentStack<T>
- Implements
Inherited Members
System.Object
Examples
The following example shows how to use a ConcurrentStack<T> to push and pop individual items:
class CS_Singles
{
// Demonstrates:
// ConcurrentStack<T>.Push();
// ConcurrentStack<T>.TryPeek();
// ConcurrentStack<T>.TryPop();
// ConcurrentStack<T>.Clear();
// ConcurrentStack<T>.IsEmpty;
static void Main ()
{
int errorCount = 0;
// Construct a ConcurrentStack
ConcurrentStack<int> cs = new ConcurrentStack<int>();
// Push some elements onto the stack
cs.Push(1);
cs.Push(2);
int result;
// Peek at the top of the stack
if (!cs.TryPeek(out result))
{
Console.WriteLine("CS: TryPeek() failed when it should have succeeded");
errorCount++;
}
else if (result != 2)
{
Console.WriteLine("CS: TryPeek() saw {0} instead of 2", result);
errorCount++;
}
// Pop a number off of the stack
if (!cs.TryPop(out result))
{
Console.WriteLine("CS: TryPop() failed when it should have succeeded");
errorCount++;
}
else if (result != 2)
{
Console.WriteLine("CS: TryPop() saw {0} instead of 2", result);
errorCount++;
}
// Clear the stack, and verify that it is empty
cs.Clear();
if (!cs.IsEmpty)
{
Console.WriteLine("CS: IsEmpty not true after Clear()");
errorCount++;
}
if (errorCount == 0) Console.WriteLine(" OK!");
}
}
' Imports System.Collections.Concurrent
Class CS_Singles
' Demonstrates:
' ConcurrentStack<T>.Push();
' ConcurrentStack<T>.TryPeek();
' ConcurrentStack<T>.TryPop();
' ConcurrentStack<T>.Clear();
' ConcurrentStack<T>.IsEmpty;
Shared Sub Main()
Dim errorCount As Integer = 0
' Construct a ConcurrentStack
Dim cs As New ConcurrentStack(Of Integer)()
' Push some elements onto the stack
cs.Push(1)
cs.Push(2)
Dim result As Integer
' Peek at the top of the stack
If Not cs.TryPeek(result) Then
Console.WriteLine("CS: TryPeek() failed when it should have succeeded")
errorCount += 1
ElseIf result <> 2 Then
Console.WriteLine("CS: TryPeek() saw {0} instead of 2", result)
errorCount += 1
End If
' Pop a number off of the stack
If Not cs.TryPop(result) Then
Console.WriteLine("CS: TryPop() failed when it should have succeeded")
errorCount += 1
ElseIf result <> 2 Then
Console.WriteLine("CS: TryPop() saw {0} instead of 2", result)
errorCount += 1
End If
' Clear the stack, and verify that it is empty
cs.Clear()
If Not cs.IsEmpty Then
Console.WriteLine("CS: IsEmpty not true after Clear()")
errorCount += 1
End If
If errorCount = 0 Then
Console.WriteLine(" OK!")
End If
End Sub
End Class
The following example shows how to use a ConcurrentStack<T> to push and pop ranges of items:
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class CS_Ranges
{
// Demonstrates:
// ConcurrentStack<T>.PushRange();
// ConcurrentStack<T>.TryPopRange();
// ConcurrentStack<T>.IsEmpty;
static void Main ()
{
int errorCount = 0;
// Construct a ConcurrentStack
ConcurrentStack<int> cs = new ConcurrentStack<int>();
// Push some consecutively numbered ranges
cs.PushRange(new int[] { 1, 2, 3, 4, 5, 6, 7 });
cs.PushRange(new int[] { 8, 9, 10 });
cs.PushRange(new int[] { 11, 12, 13, 14 });
cs.PushRange(new int[] { 15, 16, 17, 18, 19, 20 });
cs.PushRange(new int[] { 21, 22 });
cs.PushRange(new int[] { 23, 24, 25, 26, 27, 28, 29, 30 });
// Now read them back, 3 at a time, concurrently
Parallel.For(0, 10, i =>
{
int[] range = new int[3];
if (cs.TryPopRange(range) != 3)
{
Console.WriteLine("CS: TryPopRange failed unexpectedly");
Interlocked.Increment(ref errorCount);
}
// Each range should be consecutive integers, if the range was extracted atomically
// And it should be reverse of the original order...
if (!range.Skip(1).SequenceEqual(range.Take(range.Length - 1).Select(x => x - 1)))
{
Console.WriteLine("CS: Expected consecutive ranges. range[0]={0}, range[1]={1}", range[0], range[1]);
Interlocked.Increment(ref errorCount);
}
});
// We should have emptied the thing
if (!cs.IsEmpty)
{
Console.WriteLine("CS: Expected IsEmpty to be true after emptying");
errorCount++;
}
if (errorCount == 0) Console.WriteLine(" OK!");
}
}
Imports System.Collections.Concurrent
Imports System.Threading
Imports System.Threading.Tasks
Class CS_Ranges
' Demonstrates:
' ConcurrentStack<T>.PushRange();
' ConcurrentStack<T>.TryPopRange();
' ConcurrentStack<T>.IsEmpty;
Shared Sub Main()
Dim errorCount As Integer = 0
' Construct a ConcurrentStack
Dim cs As New ConcurrentStack(Of Integer)()
' Push some consecutively numbered ranges
cs.PushRange(New Integer() {1, 2, 3, 4, 5, 6, 7})
cs.PushRange(New Integer() {8, 9, 10})
cs.PushRange(New Integer() {11, 12, 13, 14})
cs.PushRange(New Integer() {15, 16, 17, 18, 19, 20})
cs.PushRange(New Integer() {21, 22})
cs.PushRange(New Integer() {23, 24, 25, 26, 27, 28, 29, 30})
' Now read them back, 3 at a time, concurrently
Parallel.For(0, 10,
Sub(i)
Dim range As Integer() = New Integer(2) {}
If cs.TryPopRange(range) <> 3 Then
Console.WriteLine("CS: TryPopRange failed unexpectedly")
Interlocked.Increment(errorCount)
End If
' Each range should be consecutive integers, if the range was extracted atomically
' And it should be reverse of the original order...
If Not range.Skip(1).SequenceEqual(range.Take(range.Length - 1).[Select](Function(x) x - 1)) Then
Console.WriteLine("CS: Expected consecutive ranges. range[0]={0}, range[1]={1}", range(0), range(1))
Interlocked.Increment(errorCount)
End If
End Sub)
' We should have emptied the thing
If Not cs.IsEmpty Then
Console.WriteLine("CS: Expected IsEmpty to be true after emptying")
errorCount += 1
End If
If errorCount = 0 Then
Console.WriteLine(" OK!")
End If
End Sub
End Class
Remarks
Note
ConcurrentStack<T> implements the IReadOnlyCollection<T> interface starting with the .NET Framework 4.6; in previous versions of the .NET Framework, the ConcurrentStack<T> class did not implement this interface.
ConcurrentStack<T> provides a few main operations:
Push inserts an element at the top of the ConcurrentStack<T>.
TryPop removes an element from the top of the ConcurrentStack<T>, or returns
falseif the item cannot be removed.TryPeek returns an element that is at the top of the ConcurrentStack<T> but does not remove it from the ConcurrentStack<T>.
The TryPopRange and PushRange methods provide efficient pushing and popping of multiple elements in a single operation.
Constructors
| ConcurrentStack<T>() |
Initializes a new instance of the ConcurrentStack<T> class. |
| ConcurrentStack<T>(IEnumerable<T>) |
Initializes a new instance of the ConcurrentStack<T> class that contains elements copied from the specified collection |
Properties
| Count |
Gets the number of elements contained in the ConcurrentStack<T>. |
| IsEmpty |
Gets a value that indicates whether the ConcurrentStack<T> is empty. |
Methods
| Clear() |
Removes all objects from the ConcurrentStack<T>. |
| CopyTo(T[], Int32) |
Copies the ConcurrentStack<T> elements to an existing one-dimensional Array, starting at the specified array index. |
| GetEnumerator() |
Returns an enumerator that iterates through the ConcurrentStack<T>. |
| Push(T) |
Inserts an object at the top of the ConcurrentStack<T>. |
| PushRange(T[]) |
Inserts multiple objects at the top of the ConcurrentStack<T> atomically. |
| PushRange(T[], Int32, Int32) |
Inserts multiple objects at the top of the ConcurrentStack<T> atomically. |
| ToArray() |
Copies the items stored in the ConcurrentStack<T> to a new array. |
| TryPeek(T) |
Attempts to return an object from the top of the ConcurrentStack<T> without removing it. |
| TryPop(T) |
Attempts to pop and return the object at the top of the ConcurrentStack<T>. |
| TryPopRange(T[], Int32, Int32) |
Attempts to pop and return multiple objects from the top of the ConcurrentStack<T> atomically. |
| TryPopRange(T[]) |
Attempts to pop and return multiple objects from the top of the ConcurrentStack<T> atomically. |
Explicit Interface Implementations
| IProducerConsumerCollection<T>.TryAdd(T) |
Attempts to add an object to the IProducerConsumerCollection<T>. |
| IProducerConsumerCollection<T>.TryTake(T) |
Attempts to remove and return an object from the IProducerConsumerCollection<T>. |
| ICollection.CopyTo(Array, Int32) |
Copies the elements of the ICollection to an Array, starting at a particular Array index. |
| ICollection.IsSynchronized |
Gets a value indicating whether access to the ICollection is synchronized with the SyncRoot. |
| ICollection.SyncRoot |
Gets an object that can be used to synchronize access to the ICollection. This property is not supported. |
| IEnumerable.GetEnumerator() |
Returns an enumerator that iterates through a collection. |
Extension Methods
Thread Safety
All public and protected members of ConcurrentStack<T> are thread-safe and may be used concurrently from multiple threads.