ConcurrentStack<T> 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
表示线程安全最后一次传入 (LIFO) 集合。
generic <typename T>
public ref class ConcurrentStack : System::Collections::Concurrent::IProducerConsumerCollection<T>, System::Collections::Generic::IEnumerable<T>, System::Collections::Generic::IReadOnlyCollection<T>, System::Collections::ICollection
generic <typename T>
public ref class ConcurrentStack : System::Collections::Concurrent::IProducerConsumerCollection<T>, System::Collections::Generic::IEnumerable<T>
generic <typename T>
public ref class ConcurrentStack : System::Collections::Concurrent::IProducerConsumerCollection<T>, System::Collections::Generic::IEnumerable<T>, System::Collections::Generic::IReadOnlyCollection<T>
generic <typename T>
public ref class ConcurrentStack : System::Collections::Concurrent::IProducerConsumerCollection<T>, System::Collections::Generic::IEnumerable<T>, System::Collections::ICollection
public class ConcurrentStack<T> : System.Collections.Concurrent.IProducerConsumerCollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.ICollection
[System.Serializable]
public class ConcurrentStack<T> : System.Collections.Concurrent.IProducerConsumerCollection<T>, System.Collections.Generic.IEnumerable<T>
[System.Serializable]
public class ConcurrentStack<T> : System.Collections.Concurrent.IProducerConsumerCollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>
public class ConcurrentStack<T> : System.Collections.Concurrent.IProducerConsumerCollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.ICollection
public class ConcurrentStack<T> : System.Collections.Concurrent.IProducerConsumerCollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>
type ConcurrentStack<'T> = class
interface IProducerConsumerCollection<'T>
interface seq<'T>
interface IEnumerable
interface ICollection
interface IReadOnlyCollection<'T>
[<System.Serializable>]
type ConcurrentStack<'T> = class
interface IProducerConsumerCollection<'T>
interface seq<'T>
interface ICollection
interface IEnumerable
[<System.Serializable>]
type ConcurrentStack<'T> = class
interface IProducerConsumerCollection<'T>
interface seq<'T>
interface IEnumerable
interface ICollection
interface IReadOnlyCollection<'T>
type ConcurrentStack<'T> = class
interface IProducerConsumerCollection<'T>
interface seq<'T>
interface ICollection
interface IEnumerable
Public Class ConcurrentStack(Of T)
Implements ICollection, IEnumerable(Of T), IProducerConsumerCollection(Of T), IReadOnlyCollection(Of T)
Public Class ConcurrentStack(Of T)
Implements IEnumerable(Of T), IProducerConsumerCollection(Of T)
Public Class ConcurrentStack(Of T)
Implements IEnumerable(Of T), IProducerConsumerCollection(Of T), IReadOnlyCollection(Of T)
Public Class ConcurrentStack(Of T)
Implements ICollection, IEnumerable(Of T), IProducerConsumerCollection(Of T)
类型参数
- T
堆栈中包含的元素的类型。
- 继承
-
ConcurrentStack<T>
- 属性
- 实现
示例
以下示例演示如何使用 ConcurrentStack<T> 推送和弹出单个项:
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
class Example
{
// Demonstrates:
// ConcurrentStack<T>.Push();
// ConcurrentStack<T>.TryPeek();
// ConcurrentStack<T>.TryPop();
// ConcurrentStack<T>.Clear();
// ConcurrentStack<T>.IsEmpty;
static async Task Main()
{
int items = 10000;
ConcurrentStack<int> stack = new ConcurrentStack<int>();
// Create an action to push items onto the stack
Action pusher = () =>
{
for (int i = 0; i < items; i++)
{
stack.Push(i);
}
};
// Run the action once
pusher();
if (stack.TryPeek(out int result))
{
Console.WriteLine($"TryPeek() saw {result} on top of the stack.");
}
else
{
Console.WriteLine("Could not peek most recently added number.");
}
// Empty the stack
stack.Clear();
if (stack.IsEmpty)
{
Console.WriteLine("Cleared the stack.");
}
// Create an action to push and pop items
Action pushAndPop = () =>
{
Console.WriteLine($"Task started on {Task.CurrentId}");
int item;
for (int i = 0; i < items; i++)
stack.Push(i);
for (int i = 0; i < items; i++)
stack.TryPop(out item);
Console.WriteLine($"Task ended on {Task.CurrentId}");
};
// Spin up five concurrent tasks of the action
var tasks = new Task[5];
for (int i = 0; i < tasks.Length; i++)
tasks[i] = Task.Factory.StartNew(pushAndPop);
// Wait for all the tasks to finish up
await Task.WhenAll(tasks);
if (!stack.IsEmpty)
{
Console.WriteLine("Did not take all the items off the stack");
}
}
}
open System
open System.Collections.Concurrent
open System.Threading.Tasks
// Demonstrates:
// ConcurrentStack<T>.Push();
// ConcurrentStack<T>.TryPeek();
// ConcurrentStack<T>.TryPop();
// ConcurrentStack<T>.Clear();
// ConcurrentStack<T>.IsEmpty;
let main =
task {
let items = 10000
let stack = ConcurrentStack<int>()
// Create an action to push items onto the stack
let pusher =
Action(fun () ->
for i = 0 to items - 1 do
stack.Push i)
// Run the action once
pusher.Invoke()
let mutable result = 0
if stack.TryPeek &result then
printfn $"TryPeek() saw {result} on top of the stack."
else
printfn "Could not peek most recently added number."
// Empty the stack
stack.Clear()
if stack.IsEmpty then
printfn "Cleared the stack."
// Create an action to push and pop items
let pushAndPop =
Action(fun () ->
printfn $"Task started on {Task.CurrentId}"
let mutable item = 0
for i = 0 to items - 1 do
stack.Push i
for i = 0 to items - 1 do
stack.TryPop &item |> ignore
printfn $"Task ended on {Task.CurrentId}")
// Spin up five concurrent tasks of the action
let tasks =
[| for i = 0 to 4 do
Task.Run pushAndPop |]
// Wait for all the tasks to finish up
do! Task.WhenAll tasks
if not stack.IsEmpty then
printfn "Did not take all the items off the stack"
}
main.Wait()
Imports System.Collections.Concurrent
Imports System.Threading.Tasks
Class Example
' Demonstrates:
' ConcurrentStack<T>.Push();
' ConcurrentStack<T>.TryPeek();
' ConcurrentStack<T>.TryPop();
' ConcurrentStack<T>.Clear();
' ConcurrentStack<T>.IsEmpty;
Shared Sub Main()
Dim items As Integer = 10000
Dim stack As ConcurrentStack(Of Integer) = New ConcurrentStack(Of Integer)()
' Create an action to push items onto the stack
Dim pusher As Action = Function()
For i As Integer = 0 To items - 1
stack.Push(i)
Next
End Function
' Run the action once
pusher()
Dim result As Integer = Nothing
If stack.TryPeek(result) Then
Console.WriteLine($"TryPeek() saw {result} on top of the stack.")
Else
Console.WriteLine("Could not peek most recently added number.")
End If
' Empty the stack
stack.Clear()
If stack.IsEmpty Then
Console.WriteLine("Cleared the stack.")
End If
' Create an action to push and pop items
Dim pushAndPop As Action = Function()
Console.WriteLine($"Task started on {Task.CurrentId}")
Dim item As Integer
For i As Integer = 0 To items - 1
stack.Push(i)
Next
For i As Integer = 0 To items - 1
stack.TryPop(item)
Next
Console.WriteLine($"Task ended on {Task.CurrentId}")
End Function
' Spin up five concurrent tasks of the action
Dim tasks = New Task(4) {}
For i As Integer = 0 To tasks.Length - 1
tasks(i) = Task.Factory.StartNew(pushAndPop)
Next
' Wait for all the tasks to finish up
Task.WaitAll(tasks)
If Not stack.IsEmpty Then
Console.WriteLine("Did not take all the items off the stack")
End If
End Sub
End Class
以下示例演示如何使用 ConcurrentStack<T> 推送和弹出项范围:
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class Example
{
// Demonstrates:
// ConcurrentStack<T>.PushRange();
// ConcurrentStack<T>.TryPopRange();
static async Task Main()
{
int numParallelTasks = 4;
int numItems = 1000;
var stack = new ConcurrentStack<int>();
// Push a range of values onto the stack concurrently
await Task.WhenAll(Enumerable.Range(0, numParallelTasks).Select(i => Task.Factory.StartNew((state) =>
{
// state = i * numItems
int index = (int)state;
int[] array = new int[numItems];
for (int j = 0; j < numItems; j++)
{
array[j] = index + j;
}
Console.WriteLine($"Pushing an array of ints from {array[0]} to {array[numItems - 1]}");
stack.PushRange(array);
}, i * numItems, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default)).ToArray());
int numTotalElements = 4 * numItems;
int[] resultBuffer = new int[numTotalElements];
await Task.WhenAll(Enumerable.Range(0, numParallelTasks).Select(i => Task.Factory.StartNew(obj =>
{
int index = (int)obj;
int result = stack.TryPopRange(resultBuffer, index, numItems);
Console.WriteLine($"TryPopRange expected {numItems}, got {result}.");
}, i * numItems, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default)).ToArray());
for (int i = 0; i < numParallelTasks; i++)
{
// Create a sequence we expect to see from the stack taking the last number of the range we inserted
var expected = Enumerable.Range(resultBuffer[i*numItems + numItems - 1], numItems);
// Take the range we inserted, reverse it, and compare to the expected sequence
var areEqual = expected.SequenceEqual(resultBuffer.Skip(i * numItems).Take(numItems).Reverse());
if (areEqual)
{
Console.WriteLine($"Expected a range of {expected.First()} to {expected.Last()}. Got {resultBuffer[i * numItems + numItems - 1]} to {resultBuffer[i * numItems]}");
}
else
{
Console.WriteLine($"Unexpected consecutive ranges.");
}
}
}
}
open System.Collections.Concurrent
open System.Linq
open System.Threading
open System.Threading.Tasks
// Demonstrates:
// ConcurrentStack<T>.PushRange();
// ConcurrentStack<T>.TryPopRange();
let main =
task {
let numParallelTasks = 4
let numItems = 1000
let stack = ConcurrentStack<int>()
// Push a range of values onto the stack concurrently
let! _ = Task.WhenAll(Enumerable.Range(0, numParallelTasks).Select(fun i ->
Task.Factory.StartNew((fun state ->
// state = i * numItems
let index: int = unbox state
let array =
[| for j in 0 .. numItems - 1 do
index + j |]
printfn $"Pushing an array of ints from {array[0]} to {array[numItems - 1]}"
stack.PushRange array
), i * numItems, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default)).ToArray())
let numTotalElements = 4 * numItems
let resultBuffer = Array.zeroCreate numTotalElements
let! _ = Task.WhenAll(Enumerable.Range(0, numParallelTasks).Select(fun i ->
Task.Factory.StartNew((fun obj ->
let index = unbox obj
let result = stack.TryPopRange(resultBuffer, index, numItems)
printfn $"TryPopRange expected {numItems}, got {result}."
), i * numItems, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default)).ToArray())
for i = 0 to numParallelTasks - 1 do
// Create a sequence we expect to see from the stack taking the last number of the range we inserted
let expected = Enumerable.Range(resultBuffer[i*numItems + numItems - 1], numItems)
// Take the range we inserted, reverse it, and compare to the expected sequence
let areEqual = expected.SequenceEqual(resultBuffer.Skip(i * numItems).Take(numItems).Reverse())
if areEqual then
printfn $"Expected a range of {expected.First()} to {expected.Last()}. Got {resultBuffer[i * numItems + numItems - 1]} to {resultBuffer[i * numItems]}"
else
printfn $"Unexpected consecutive ranges."
}
main.Wait()
Imports System.Collections.Concurrent
Imports System.Linq
Imports System.Threading
Imports System.Threading.Tasks
Class Example
' Demonstrates:
' ConcurrentStack<T>.PushRange();
' ConcurrentStack<T>.TryPopRange();
Shared Sub Main()
Dim numParallelTasks As Integer = 4
Dim numItems As Integer = 1000
Dim stack = New ConcurrentStack(Of Integer)()
' Push a range of values onto the stack concurrently
Task.WaitAll(Enumerable.Range(0, numParallelTasks).[Select](
Function(i) Task.Factory.StartNew(
Function(state)
Dim index As Integer = CInt(state)
Dim array As Integer() = New Integer(numItems - 1) {}
For j As Integer = 0 To numItems - 1
array(j) = index + j
Next
Console.WriteLine($"Pushing an array of ints from {array(0)} to {array(numItems - 1)}")
stack.PushRange(array)
End Function, i * numItems, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.[Default])).ToArray())
Dim numTotalElements As Integer = 4 * numItems
Dim resultBuffer As Integer() = New Integer(numTotalElements - 1) {}
Task.WaitAll(Enumerable.Range(0, numParallelTasks).[Select](
Function(i) Task.Factory.StartNew(
Function(obj)
Dim index As Integer = CInt(obj)
Dim result As Integer = stack.TryPopRange(resultBuffer, index, numItems)
Console.WriteLine($"TryPopRange expected {numItems}, got {result}.")
End Function, i * numItems, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.[Default])).ToArray())
For i As Integer = 0 To numParallelTasks - 1
' Create a sequence we expect to see from the stack taking the last number of the range we inserted
Dim expected = Enumerable.Range(resultBuffer(i * numItems + numItems - 1), numItems)
' Take the range we inserted, reverse it, and compare to the expected sequence
Dim areEqual = expected.SequenceEqual(resultBuffer.Skip(i * numItems).Take(numItems).Reverse())
If areEqual Then
Console.WriteLine($"Expected a range of {expected.First()} to {expected.Last()}. Got {resultBuffer(i * numItems + numItems - 1)} to {resultBuffer(i * numItems)}")
Else
Console.WriteLine($"Unexpected consecutive ranges.")
End If
Next
End Sub
End Class
注解
注意
ConcurrentStack<T> 从 .NET Framework 4.6 开始实现 IReadOnlyCollection<T> 接口;在早期版本的 .NET Framework 中,ConcurrentStack<T> 类未实现此接口。
ConcurrentStack<T> 提供了一些主要操作:
Push 在 ConcurrentStack<T>顶部插入元素。
TryPop 从 ConcurrentStack<T>顶部删除元素,或者如果无法删除该项,则返回
false
。TryPeek 返回位于 ConcurrentStack<T> 顶部但不会将其从 ConcurrentStack<T>中删除的元素。
TryPopRange 和 PushRange 方法在单个操作中提供高效推送和弹出多个元素。
构造函数
ConcurrentStack<T>() |
初始化 ConcurrentStack<T> 类的新实例。 |
ConcurrentStack<T>(IEnumerable<T>) |
初始化包含从指定集合复制的元素的 ConcurrentStack<T> 类的新实例。 |
属性
Count |
获取 ConcurrentStack<T>中包含的元素数。 |
IsEmpty |
获取一个值,该值指示 ConcurrentStack<T> 是否为空。 |
方法
Clear() |
从 ConcurrentStack<T>中删除所有对象。 |
CopyTo(T[], Int32) |
从指定的数组索引开始,将 ConcurrentStack<T> 元素复制到现有的一维 Array。 |
Equals(Object) |
确定指定的对象是否等于当前对象。 (继承自 Object) |
GetEnumerator() |
返回循环访问 ConcurrentStack<T>的枚举数。 |
GetHashCode() |
用作默认哈希函数。 (继承自 Object) |
GetType() |
获取当前实例的 Type。 (继承自 Object) |
MemberwiseClone() |
创建当前 Object的浅表副本。 (继承自 Object) |
Push(T) |
在 ConcurrentStack<T>顶部插入对象。 |
PushRange(T[]) |
以原子方式在 ConcurrentStack<T> 顶部插入多个对象。 |
PushRange(T[], Int32, Int32) |
以原子方式在 ConcurrentStack<T> 顶部插入多个对象。 |
ToArray() |
将存储在 ConcurrentStack<T> 中的项复制到新数组。 |
ToString() |
返回一个表示当前对象的字符串。 (继承自 Object) |
TryPeek(T) |
尝试从 ConcurrentStack<T> 顶部返回对象,而不将其删除。 |
TryPop(T) |
尝试弹出并返回 ConcurrentStack<T>顶部的对象。 |
TryPopRange(T[]) |
尝试以原子方式从 ConcurrentStack<T> 顶部弹出并返回多个对象。 |
TryPopRange(T[], Int32, Int32) |
尝试以原子方式从 ConcurrentStack<T> 顶部弹出并返回多个对象。 |
显式接口实现
ICollection.CopyTo(Array, Int32) |
从特定 Array 索引开始,将 ICollection 的元素复制到 Array。 |
ICollection.IsSynchronized |
获取一个值,该值指示对 ICollection 的访问是否与 SyncRoot 同步。 |
ICollection.SyncRoot |
获取可用于同步对 ICollection的访问的对象。 不支持此属性。 |
IEnumerable.GetEnumerator() |
返回循环访问集合的枚举器。 |
IProducerConsumerCollection<T>.TryAdd(T) |
尝试将对象添加到 IProducerConsumerCollection<T>。 |
IProducerConsumerCollection<T>.TryTake(T) |
尝试从 IProducerConsumerCollection<T>中删除和返回对象。 |
扩展方法
适用于
线程安全性
ConcurrentStack<T> 的所有公共和受保护成员都是线程安全的,可以从多个线程并发使用。