C#創建安全的棧(Stack)存儲結構

来源:http://www.cnblogs.com/pengze0902/archive/2016/10/23/5990992.html
-Advertisement-
Play Games

在C#中,用於存儲的結構較多,如:DataTable,DataSet,List,Dictionary,Stack等結構,各種結構採用的存儲的方式存在差異,效率也必然各有優缺點。現在介紹一種後進先出的數據結構。 談到存儲結構,我們在項目中使用的較多。對於Task存儲結構,棧與隊列是類似的結構,在使用的 ...


    在C#中,用於存儲的結構較多,如:DataTable,DataSet,List,Dictionary,Stack等結構,各種結構採用的存儲的方式存在差異,效率也必然各有優缺點。現在介紹一種後進先出的數據結構。

   談到存儲結構,我們在項目中使用的較多。對於Task存儲結構,棧與隊列是類似的結構,在使用的時候採用不同的方法。C#中棧(Stack)是編譯期間就分配好的記憶體空間,因此你的代碼中必須就棧的大小有明確的定義;堆是程式運行期間動態分配的記憶體空間,你可以根據程式的運行情況確定要分配的堆記憶體的大小。

    在C#中,棧通常保存著我們代碼執行的步驟。C#中的引用類型存儲在棧中,在程式運行的時候,每個線程(Thread)都會維護一個自己的專屬線程堆棧。當一個方法被調用的時候,主線程開始在所屬程式集的元數據中,查找被調用方法,然後通過JIT即時編譯並把結果(一般是本地CPU指令)放在棧頂。CPU通過匯流排從棧頂取指令,驅動程式以執行下去。

    以上對棧這個數據結構進行了一個簡單的介紹,現在看一下C#實現棧結構的底層方法:

   /// <summary>
    /// 初始化 <see cref="T:System.Collections.Generic.Stack`1"/> 類的新實例,該實例為空並且具有預設初始容量。
    /// </summary>
    [__DynamicallyInvokable]
    public Stack();
    /// <summary>
    /// 初始化 <see cref="T:System.Collections.Generic.Stack`1"/> 類的新實例,該實例為空,具有指定的初始容量或預設的初始容量(其中較大的一個)。
    /// </summary>
    /// <param name="capacity"><see cref="T:System.Collections.Generic.Stack`1"/> 可包含的初始元素數。</param><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="capacity"/> is less than zero.</exception>
    [__DynamicallyInvokable]
    public Stack(int capacity);
    /// <summary>
    /// 初始化 <see cref="T:System.Collections.Generic.Stack`1"/> 類的新實例,該實例包含從指定集合複製的元素並且具有足夠的容量來容納所複製的元素。
    /// </summary>
    /// <param name="collection">從中複製元素的集合。</param><exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is null.</exception>
    [__DynamicallyInvokable]
    public Stack(IEnumerable<T> collection);

   以上是對stack的部分方法的介紹,由於在操作數據存儲的同時,會考慮到線程的安全性。

   進程作為操作系統執行程式的基本單位,擁有應用程式的資源,進程包含線程,進程的資源被線程共用,線程不擁有資源。線程分為前臺線程和後臺線程,通過Thread類新建線程預設為前臺線程。當所有前臺線程關閉時,所有的後臺線程也會被直接終止,不會拋出異常。

    接下來看一下ReaderWriterLockSlim類:

/// <summary>
  /// 表示用於管理資源訪問的鎖定狀態,可實現多線程讀取或進行獨占式寫入訪問。
  /// </summary>
  [__DynamicallyInvokable]
  [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true, Synchronization = true)]
  [HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort = true)]
  public class ReaderWriterLockSlim : IDisposable
  {
    /// <summary>
    /// 使用預設屬性值初始化 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 類的新實例。
    /// </summary>
    [__DynamicallyInvokable]
    public ReaderWriterLockSlim();
    /// <summary>
    /// 在指定鎖定遞歸策略的情況下初始化 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 類的新實例。
    /// </summary>
    /// <param name="recursionPolicy">枚舉值之一,用於指定鎖定遞歸策略。</param>
    [__DynamicallyInvokable]
    public ReaderWriterLockSlim(LockRecursionPolicy recursionPolicy);
    /// <summary>
    /// 嘗試進入讀取模式鎖定狀態。
    /// </summary>
    /// <exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 屬性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和當前的線程已進入讀取的模式。- 或 -當它已經包含寫入鎖時,當前線程可能不會獲取讀的鎖定。- 或 -遞歸數將超出該計數器的容量。此限制是很大的應用程式應永遠不會遇到它。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 對象已被釋放。</exception>
    [__DynamicallyInvokable]
    public void EnterReadLock();
    /// <summary>
    /// 嘗試進入讀取模式鎖定狀態,可以選擇超時時間。
    /// </summary>
    /// 
    /// <returns>
    /// 如果調用線程已進入讀取模式,則為 true;否則為 false。
    /// </returns>
    /// <param name="timeout">等待的間隔;或為 -1 毫秒,表示無限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 屬性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和當前的線程已進入該鎖。- 或 -遞歸數將超出該計數器的容量。限製為應用程式應永遠不會遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> 為負數,但它不等於-1 毫秒為單位),這是唯一允許的值為負。- 或 -值 <paramref name="timeout"/> 大於 <see cref="F:System.Int32.MaxValue"/> 毫秒為單位)。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 對象已被釋放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterReadLock(TimeSpan timeout);
    /// <summary>
    /// 嘗試進入讀取模式鎖定狀態,可以選擇整數超時時間。
    /// </summary>
    /// 
    /// <returns>
    /// 如果調用線程已進入讀取模式,則為 true;否則為 false。
    /// </returns>
    /// <param name="millisecondsTimeout">等待的毫秒數,或為 -1 (<see cref="F:System.Threading.Timeout.Infinite"/>),表示無限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 屬性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和當前的線程已進入該鎖。- 或 -遞歸數將超出該計數器的容量。限製為應用程式應永遠不會遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> 為負數,但它不是等於 <see cref="F:System.Threading.Timeout.Infinite"/> (-1),這是唯一允許的值為負。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 對象已被釋放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterReadLock(int millisecondsTimeout);
    /// <summary>
    /// 嘗試進入寫入模式鎖定狀態。
    /// </summary>
    /// <exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 屬性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和當前的線程已在任何模式下進入該鎖。- 或 -當前線程已進入讀取的模式,因此嘗試進入鎖定狀態寫模式,則會創建導致死鎖的可能性。- 或 -遞歸數將超出該計數器的容量。限製為應用程式應永遠不會遇到它太大。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 對象已被釋放。</exception>
    [__DynamicallyInvokable]
    public void EnterWriteLock();
    /// <summary>
    /// 嘗試進入寫入模式鎖定狀態,可以選擇超時時間。
    /// </summary>
    /// 
    /// <returns>
    /// 如果調用線程已進入寫入模式,則為 true;否則為 false。
    /// </returns>
    /// <param name="timeout">等待的間隔;或為 -1 毫秒,表示無限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 屬性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和當前的線程已進入該鎖。- 或 -當前線程最初在讀取模式中,輸入該鎖,因此嘗試進入寫入模式會創建導致死鎖的可能性。- 或 -遞歸數將超出該計數器的容量。限製為應用程式應永遠不會遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> 為負數,但它不等於-1 毫秒為單位),這是唯一允許的值為負。- 或 -值 <paramref name="timeout"/> 大於 <see cref="F:System.Int32.MaxValue"/> 毫秒為單位)。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 對象已被釋放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterWriteLock(TimeSpan timeout);
    /// <summary>
    /// 嘗試進入寫入模式鎖定狀態,可以選擇超時時間。
    /// </summary>
    /// 
    /// <returns>
    /// 如果調用線程已進入寫入模式,則為 true;否則為 false。
    /// </returns>
    /// <param name="millisecondsTimeout">等待的毫秒數,或為 -1 (<see cref="F:System.Threading.Timeout.Infinite"/>),表示無限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 屬性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和當前的線程已進入該鎖。- 或 -當前線程最初在讀取模式中,輸入該鎖,因此嘗試進入寫入模式會創建導致死鎖的可能性。- 或 -遞歸數將超出該計數器的容量。限製為應用程式應永遠不會遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> 為負數,但它不是等於 <see cref="F:System.Threading.Timeout.Infinite"/> (-1),這是唯一允許的值為負。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 對象已被釋放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterWriteLock(int millisecondsTimeout);
    /// <summary>
    /// 嘗試進入可升級模式鎖定狀態。
    /// </summary>
    /// <exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 屬性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和當前的線程已在任何模式下進入該鎖。- 或 -當前線程已進入讀取的模式,因此嘗試進入可升級模式將有死鎖的可能性。- 或 -遞歸數將超出該計數器的容量。限製為應用程式應永遠不會遇到它太大。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 對象已被釋放。</exception>
    [__DynamicallyInvokable]
    public void EnterUpgradeableReadLock();
    /// <summary>
    /// 嘗試進入可升級模式鎖定狀態,可以選擇超時時間。
    /// </summary>
    /// 
    /// <returns>
    /// 如果調用線程已進入可升級模式,則為 true;否則為 false。
    /// </returns>
    /// <param name="timeout">等待的間隔;或為 -1 毫秒,表示無限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 屬性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和當前的線程已進入該鎖。- 或 -當前線程最初在讀取模式中,輸入該鎖,因此嘗試進入可升級模式會創建導致死鎖的可能性。- 或 -遞歸數將超出該計數器的容量。限製為應用程式應永遠不會遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> 為負數,但它不等於-1 毫秒為單位),這是唯一允許的值為負。- 或 -值 <paramref name="timeout"/> 大於 <see cref="F:System.Int32.MaxValue"/> 毫秒為單位)。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 對象已被釋放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterUpgradeableReadLock(TimeSpan timeout);
    /// <summary>
    /// 嘗試進入可升級模式鎖定狀態,可以選擇超時時間。
    /// </summary>
    /// 
    /// <returns>
    /// 如果調用線程已進入可升級模式,則為 true;否則為 false。
    /// </returns>
    /// <param name="millisecondsTimeout">等待的毫秒數,或為 -1 (<see cref="F:System.Threading.Timeout.Infinite"/>),表示無限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 屬性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和當前的線程已進入該鎖。- 或 -當前線程最初在讀取模式中,輸入該鎖,因此嘗試進入可升級模式會創建導致死鎖的可能性。- 或 -遞歸數將超出該計數器的容量。限製為應用程式應永遠不會遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> 為負數,但它不是等於 <see cref="F:System.Threading.Timeout.Infinite"/> (-1),這是唯一允許的值為負。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 對象已被釋放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterUpgradeableReadLock(int millisecondsTimeout);
    /// <summary>
    /// 減少讀取模式的遞歸計數,併在生成的計數為 0(零)時退出讀取模式。
    /// </summary>
    /// <exception cref="T:System.Threading.SynchronizationLockException">在讀取模式中,當前線程不已進入該鎖。</exception>
    [__DynamicallyInvokable]
    public void ExitReadLock();
    /// <summary>
    /// 減少寫入模式的遞歸計數,併在生成的計數為 0(零)時退出寫入模式。
    /// </summary>
    /// <exception cref="T:System.Threading.SynchronizationLockException">當前線程不已進入寫入模式的鎖定。</exception>
    [__DynamicallyInvokable]
    public void ExitWriteLock();
    /// <summary>
    /// 減少可升級模式的遞歸計數,併在生成的計數為 0(零)時退出可升級模式。
    /// </summary>
    /// <exception cref="T:System.Threading.SynchronizationLockException">當前線程不已進入可升級模式的鎖定。</exception>
    [__DynamicallyInvokable]
    public void ExitUpgradeableReadLock();
    /// <summary>
    /// 釋放 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 類的當前實例所使用的所有資源。
    /// </summary>
    /// <exception cref="T:System.Threading.SynchronizationLockException"><see cref="P:System.Threading.ReaderWriterLockSlim.WaitingReadCount"/> 是大於零。- 或 -<see cref="P:System.Threading.ReaderWriterLockSlim.WaitingUpgradeCount"/> 是大於零。- 或 -<see cref="P:System.Threading.ReaderWriterLockSlim.WaitingWriteCount"/> 是大於零。</exception><filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public void Dispose();
    /// <summary>
    /// 獲取一個值,該值指示當前線程是否已進入讀取模式的鎖定狀態。
    /// </summary>
    /// 
    /// <returns>
    /// 如果當前線程已進入讀取模式,則為 true;否則為 false。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public bool IsReadLockHeld { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 獲取一個值,該值指示當前線程是否已進入可升級模式的鎖定狀態。
    /// </summary>
    /// 
    /// <returns>
    /// 如果當前線程已進入可升級模式,則為 true;否則為 false。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public bool IsUpgradeableReadLockHeld { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 獲取一個值,該值指示當前線程是否已進入寫入模式的鎖定狀態。
    /// </summary>
    /// 
    /// <returns>
    /// 如果當前線程已進入寫入模式,則為 true;否則為 false。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public bool IsWriteLockHeld { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 獲取一個值,該值指示當前 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 對象的遞歸策略。
    /// </summary>
    /// 
    /// <returns>
    /// 枚舉值之一,用於指定鎖定遞歸策略。
    /// </returns>
    [__DynamicallyInvokable]
    public LockRecursionPolicy RecursionPolicy { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 獲取已進入讀取模式鎖定狀態的獨有線程的總數。
    /// </summary>
    /// 
    /// <returns>
    /// 已進入讀取模式鎖定狀態的獨有線程的數量。
    /// </returns>
    [__DynamicallyInvokable]
    public int CurrentReadCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 獲取當前線程進入讀取模式鎖定狀態的次數,用於指示遞歸。
    /// </summary>
    /// 
    /// <returns>
    /// 如果當前線程未進入讀取模式,則為 0(零);如果線程已進入讀取模式但卻不是以遞歸方式進入的,則為 1;或者如果線程已經以遞歸方式進入鎖定模式 n - 1 次,則為 n。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int RecursiveReadCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 獲取當前線程進入可升級模式鎖定狀態的次數,用於指示遞歸。
    /// </summary>
    /// 
    /// <returns>
    /// 如果當前線程沒有進入可升級模式,則為 0;如果線程已進入可升級模式卻不是以遞歸方式進入的,則為 1;或者如果線程已經以遞歸方式進入可升級模式 n - 1 次,則為 n。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int RecursiveUpgradeCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 獲取當前線程進入寫入模式鎖定狀態的次數,用於指示遞歸。
    /// </summary>
    /// 
    /// <returns>
    /// 如果當前線程沒有進入寫入模式,則為 0;如果線程已進入寫入模式卻不是以遞歸方式進入的,則為 1;或者如果線程已經以遞歸方式進入寫入模式 n - 1 次,則為 n。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int RecursiveWriteCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 獲取等待進入讀取模式鎖定狀態的線程總數。
    /// </summary>
    /// 
    /// <returns>
    /// 等待進入讀取模式的線程總數。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int WaitingReadCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 獲取等待進入可升級模式鎖定狀態的線程總數。
    /// </summary>
    /// 
    /// <returns>
    /// 等待進入可升級模式的線程總數。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int WaitingUpgradeCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 獲取等待進入寫入模式鎖定狀態的線程總數。
    /// </summary>
    /// 
    /// <returns>
    /// 等待進入寫入模式的線程總數。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int WaitingWriteCount { [__DynamicallyInvokable] get; }
  }

     以上是對Stack和線程的相關知識的淺述,現在介紹一下線程安全的Stack:

 

     /// <summary>
    /// 表示對象的後進先出線程安全集合(棧結構)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class TStack<T> : IEnumerable<T>, ICollection
    {
        /// <summary>
        /// 內部堆棧
        /// </summary>
        private readonly Stack<T> _mStack;

        /// <summary>
        /// 鎖訪問堆棧(用於管理資源訪問的鎖定狀態,可實現多線程讀取或進行獨占式寫入訪問。)
        /// </summary>
        private readonly ReaderWriterLockSlim _lockStack = new ReaderWriterLockSlim();

        /// <summary>
        /// 僅用於SyncRoot屬性
        /// </summary>
        private readonly object _objSyncRoot = new object();

        // Variables
        /// <summary>
        /// 初始化一個新的實例 <see cref="TStack{T}"/> class.
        /// </summary>
        public TStack()
        {
            _mStack = new Stack<T>();
        }

        /// <summary>
        /// 初始化一個新的實例 <see cref="TStack{T}"/> class.
        /// </summary>
        /// <param name="col">
        /// 開始集合
        /// </param>
        public TStack(IEnumerable<T> col)
        {
            _mStack = new Stack<T>(col);
        }

        // Init
        /// <summary>
        /// 獲取枚舉器
        /// </summary>
        public IEnumerator<T> GetEnumerator()
        {
            Stack<T> localStack = null;

            // 初始化枚舉器
            _lockStack.PerformUsingReadLock(() =>
            {
                // 創建一個m_tlist副本
                localStack = new Stack<T>(_mStack);
            });

            // 獲取枚舉器
            foreach (T item in localStack)
                yield return item;
        }


        /// <summary>
        /// 獲取枚舉器
        /// </summary>
        IEnumerator IEnumerable.GetEnumerator()
        {
            Stack<T> localStack = null;

            // 初始化枚舉器
            _lockStack.PerformUsingReadLock(() =>
            {
                // 創建一個m_TList的副本
                localStack = new Stack<T>(_mStack);
            });

            // 獲取枚舉器
            foreach (T item in localStack)
                yield return item;
        }


        /// <summary>
        /// 複製到一個數組
        /// </summary>
        /// <param name="array"></param>
        /// <param name="index"></param>
        public void CopyTo(Array array, int index)
        {
            _lockStack.PerformUsingReadLock(() => _mStack.ToArray().CopyTo(array, index));
        }

        /// <summary>
        ///堆棧中的項目數
        /// </summary>
        public int Count
        {
            get
            {
                return _lockStack.PerformUsingReadLock(() => _mStack.Count);
            }
        }

        /// <summary>
        /// 總為真
        /// </summary>
        public bool IsSynchronized
        {
            get { return true; }
        }

        /// <summary>
        ///同步根
        /// </summary>
        public object SyncRoot
        {
            get { return _objSyncRoot; }
        }


        /// <summary>
        ///清除集合
        /// </summary>
        public void Clear()
        {
            _lockStack.PerformUsingWriteLock(() => _mStack.Clear());
        }

        // Clear
        /// <summary>
        ///如果項目在堆棧中,則為true
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Contains(T item)
        {
            return _lockStack.PerformUsingReadLock(() => _mStack.Contains(item));
        }

        // 包含
        /// <summary>
        /// 返回堆棧中的頂部項,而不從堆棧中刪除它
        /// </summary>
        /// <returns></returns>
        public T Peek()
        {
            return _lockStack.PerformUsingReadLock(() => _mStack.Peek());
        }

        // Peek
        /// <summary>
        ///刪除並返回堆棧中的頂部項目
        /// </summary>
        /// <returns></returns>
        public T Pop()
        {
            return _lockStack.PerformUsingWriteLock(() => _mStack.Pop());
        }

        // Pop
        /// <summary>
        /// 將一個項目插入堆棧
        /// </summary>
        /// <param name="item"></param>
        public void Push(T item)
        {
            _lockStack.PerformUsingWriteLock(() => _mStack.Push(item));
        }

        // Push
        /// <summary>
        ///將堆棧轉換為數組
        /// </summary>
        /// <returns></returns>
        public T[] ToArray()
        {
            return _lockStack.PerformUsingReadLock(() => _mStack.ToArray());
        }

        // ToArray
        /// <summary>
        /// 將容量設置為堆棧中實際的元素數量
        /// </summary>
        public void TrimExcess()
        {
            _lockStack.PerformUsingWriteLock(() => _mStack.TrimExcess());
        }
    }

    以上的操作方法繼承了IEnumerable<T>, ICollection兩個介面。有興趣的,可以對IEnumerable<T>, ICollection兩個介面進行細緻的瞭解。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最前面的話:Smobiler是一個在VS環境中使用.Net語言來開發APP的開發平臺,也許比Xamarin更方便 一、目標樣式 我們要實現上圖中的效果,需要如下的操作: 1.從工具欄上的”Smobiler Components”拖動一個GridView控制項到窗體界面上 2.修改GridView控制項的 ...
  • 看院子里對EF框架和MySql的配置文章不少,但是幾乎出自一篇文章的轉載,而且這篇轉載的文章的也比較坑爹,下麵我將介紹一下我的配置過程: 第一步:安裝mysql-connector-net-6.9.9.msi(必須首先安裝這個,否則會報框架不相容的錯誤,之前有坑爹的文章沒有強調這一點,結果怎麼也走不 ...
  • var 是3.5新出的一個定義變數的類型 其實也就是弱化類型的定義 VAR可代替任何類型 編譯器會根據上下文來判斷你到底是想用什麼類型的 至於什麼情況下用到VAR 我想就是你無法確定自己將用的是什麼類型 就可以使用VAR 類似 OBJECT 但是效率比OBJECT高點。 或者通俗的講: var可以理 ...
  • DataGrid 配置表頭 欄位 中文 說明 Field 欄位 註意:mg_ 開頭的欄位為層級表頭 Title 列稱 OrderNum 序號 顯示的順序(凍結和非凍結列是兩個組的序號) Width 列寬 設置的寬度(在自適應屏幕時最後的欄位無效) dg.options.fitColumns屬性決定( ...
  • AJAX AJAX = Asynchronous JavaScript and XML(非同步的 JavaScript 和 XML)。 AJAX 不是新的編程語言,而是一種使用現有標準的新方法。 AJAX 是與伺服器交換數據並更新部分網頁的藝術,在不重新載入整個頁面的情況下。 通過在後臺與伺服器進行少 ...
  • ASP.NET Aries JSAPI 文檔說明:AR.Form、AR.Combobox ...
  • ASP.NET Aries JSAPI 文檔說明:AR.Utility ...
  • 最近新學的,C#中得三層架構 ————2016-10-23 表示層 業務邏輯層(BLL) 數據訪問層(DAL) 關聯:產生依賴關係 描述:三層體繫結構就是在客戶端和資料庫之間加一個中間層,通常情況下客戶端不能直接和資料庫進行交互,而是通過中間層和數據層進行交互的。 【表示層】 主要負責完成用戶和系統 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...