using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace SynchronizationContext{ internal interface IQueueReader: IDisposable { T Dequeue(); void ReleaseReader(); } internal interface IQueueWriter : IDisposable { void Enqueue(T data); } internal class BlockingQueue : IQueueReader , IQueueWriter , IDisposable { // use a .NET queue to store the data private Queue mQueue = new Queue (); // create a semaphore that contains the items in the queue as resources. // initialize the semaphore to zero available resources (empty queue). private Semaphore mSemaphore = new Semaphore(0, int.MaxValue); // a event that gets triggered when the reader thread is exiting private ManualResetEvent mKillThread = new ManualResetEvent(false); // wait handles that are used to unblock a Dequeue operation. // Either when there is an item in the queue // or when the reader thread is exiting. private WaitHandle[] mWaitHandles; public BlockingQueue() { mWaitHandles = new WaitHandle[2] { mSemaphore, mKillThread }; } public void Enqueue(T data) { lock (mQueue) { mQueue.Enqueue(data); //mQueue.Enqueue(data);//test } // add an available resource to the semaphore, // because we just put an item // into the queue. mSemaphore.Release(); //mSemaphore.Release(2);//test } public T Dequeue() { // wait until there is an item in the queue WaitHandle.WaitAny(mWaitHandles); lock (mQueue) { if (mQueue.Count > 0) return mQueue.Dequeue(); } return default(T); } public void ReleaseReader() { mKillThread.Set(); } void IDisposable.Dispose() { if (mSemaphore != null) { mSemaphore.Close(); mQueue.Clear(); mSemaphore = null; } } }}
出处:
namespace SynchronizationContext{ class Program { static void Main(string[] args) { BlockingQueuebq = new BlockingQueue (); //线程t1向bq中延迟插入数据 Thread t1 = new Thread(() => { Thread.Sleep(4000); bq.Enqueue("test"); }); t1.Start(); //在t1将test加入到bq前,这个操作被阻塞4s左右 string d = bq.Dequeue(); Console.WriteLine("d:" + d); //Semaphore使用保证了队列中没有东西的时候出出队列的操作都是阻塞的 string d2 = bq.Dequeue(); Console.WriteLine("d2:" + d2); string d3 = bq.Dequeue(); Console.WriteLine("d3:" + d3); } }}