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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...