What's dream?

.NET并行计算和并发11:并发接口 IProducerConsumerCollection
  1 using System;
  2 using System.Collections;
  3 using System.Collections.Generic;
  4 using System.Collections.Concurrent;
  5 using System.Linq;
  6 using System.Threading;
  7 using System.Threading.Tasks;
  8 
  9 
 10 // Sample implementation of IProducerConsumerCollection(T) 
 11 // -- in this case, a thread-safe stack.
 12 public class SafeStack<T> : IProducerConsumerCollection<T>
 13 {
 14     // Used for enforcing thread-safety
 15     private object m_lockObject = new object();
 16 
 17     // We'll use a regular old Stack for our core operations
 18     private Stack<T> m_sequentialStack = null;
 19 
 20     //
 21     // Constructors
 22     //
 23     public SafeStack()
 24     {
 25         m_sequentialStack = new Stack<T>();
 26     }
 27 
 28     public SafeStack(IEnumerable<T> collection)
 29     {
 30         m_sequentialStack = new Stack<T>(collection);
 31     }
 32 
 33     //
 34     // Safe Push/Pop support
 35     //
 36     public void Push(T item)
 37     {
 38         lock (m_lockObject) m_sequentialStack.Push(item);
 39     }
 40 
 41     public bool TryPop(out T item)
 42     {
 43         bool rval = true;
 44         lock (m_lockObject)
 45         {
 46             if (m_sequentialStack.Count == 0) { item = default(T); rval = false; }
 47             else item = m_sequentialStack.Pop();
 48         }
 49         return rval;
 50     }
 51 
 52     //
 53     // IProducerConsumerCollection(T) support
 54     //
 55     public bool TryTake(out T item)
 56     {
 57         return TryPop(out item);
 58     }
 59 
 60     public bool TryAdd(T item)
 61     {
 62         Push(item);
 63         return true; // Push doesn't fail
 64     }
 65 
 66     public T[] ToArray()
 67     {
 68         T[] rval = null;
 69         lock (m_lockObject) rval = m_sequentialStack.ToArray();
 70         return rval;
 71     }
 72 
 73     public void CopyTo(T[] array, int index)
 74     {
 75         lock (m_lockObject) m_sequentialStack.CopyTo(array, index);
 76     }
 77 
 78 
 79 
 80     //
 81     // Support for IEnumerable(T)
 82     //
 83     public IEnumerator<T> GetEnumerator()
 84     {
 85         // The performance here will be unfortunate for large stacks,
 86         // but thread-safety is effectively implemented.
 87         Stack<T> stackCopy = null;
 88         lock (m_lockObject) stackCopy = new Stack<T>(m_sequentialStack);
 89         return stackCopy.GetEnumerator();
 90     }
 91 
 92 
 93     //
 94     // Support for IEnumerable
 95     //
 96     IEnumerator IEnumerable.GetEnumerator()
 97     {
 98         return ((IEnumerable<T>)this).GetEnumerator();
 99     }
100 
101     // 
102     // Support for ICollection
103     //
104     public bool IsSynchronized
105     {
106         get { return true; }
107     }
108 
109     public object SyncRoot
110     {
111         get { return m_lockObject; }
112     }
113 
114     public int Count
115     {
116         get { return m_sequentialStack.Count; }
117     }
118 
119     public void CopyTo(Array array, int index)
120     {
121         lock (m_lockObject) ((ICollection)m_sequentialStack).CopyTo(array, index);
122     }
123 }
124 
125 public class Program
126 {
127     static void Main()
128     {
129         TestSafeStack();
130 
131         // Keep the console window open in debug mode.
132         Console.WriteLine("Press any key to exit.");
133         Console.ReadKey();
134     }
135 
136     // Test our implementation of IProducerConsumerCollection(T)
137     // Demonstrates:
138     //      IPCC(T).TryAdd()
139     //      IPCC(T).TryTake()
140     //      IPCC(T).CopyTo()
141     static void TestSafeStack()
142     {
143         SafeStack<int> stack = new SafeStack<int>();
144         IProducerConsumerCollection<int> ipcc = (IProducerConsumerCollection<int>)stack;
145 
146         // Test Push()/TryAdd()
147         stack.Push(10); Console.WriteLine("Pushed 10");
148         ipcc.TryAdd(20); Console.WriteLine("IPCC.TryAdded 20");
149         stack.Push(15); Console.WriteLine("Pushed 15");
150 
151         int[] testArray = new int[3];
152 
153         // Try CopyTo() within boundaries
154         try
155         {
156             ipcc.CopyTo(testArray, 0);
157             Console.WriteLine("CopyTo() within boundaries worked, as expected");
158         }
159         catch (Exception e)
160         {
161             Console.WriteLine("CopyTo() within boundaries unexpectedly threw an exception: {0}", e.Message);
162         }
163 
164         // Try CopyTo() that overflows
165         try
166         {
167             ipcc.CopyTo(testArray, 1);
168             Console.WriteLine("CopyTo() with index overflow worked, and it SHOULD NOT HAVE");
169         }
170         catch (Exception e)
171         {
172             Console.WriteLine("CopyTo() with index overflow threw an exception, as expected: {0}", e.Message);
173         }
174 
175         // Test enumeration
176         Console.Write("Enumeration (should be three items): ");
177         foreach (int item in stack) Console.Write("{0} ", item);
178         Console.WriteLine("");
179 
180         // Test TryPop()
181         int popped = 0;
182         if (stack.TryPop(out popped))
183         {
184             Console.WriteLine("Successfully popped {0}", popped);
185         }
186         else Console.WriteLine("FAILED to pop!!");
187 
188         // Test Count
189         Console.WriteLine("stack count is {0}, should be 2", stack.Count);
190 
191         // Test TryTake()
192         if (ipcc.TryTake(out popped))
193         {
194             Console.WriteLine("Successfully IPCC-TryTaked {0}", popped);
195         }
196         else Console.WriteLine("FAILED to IPCC.TryTake!!");
197     }
198 }
199 

posted on 2017-08-22 13:24  kiss88  阅读(447)  评论(0编辑  收藏  举报