using System; using System.Threading; using System.Collections.Generic; class ProducerConsumerQueue : IDisposable { EventWaitHandle _wh = new AutoResetEvent (false); Thread _worker; readonly object _locker = new object(); Queue<string> _tasks = new Queue<string>(); public ProducerConsumerQueue() { _worker = new Thread (Work); _worker.Start(); } public void EnqueueTask (string task) { lock (_locker) _tasks.Enqueue (task); _wh.Set(); } public void Dispose() { EnqueueTask (null); // 通知消费者退出 _worker.Join(); // 等待消费者线程完成执行 _wh.Close(); // 释放所有系统资源 } void Work() { while (true) { string task = null; lock (_locker) if (_tasks.Count > 0) { task = _tasks.Dequeue(); if (task == null) return; } if (task != null) { Console.WriteLine ("Performing task: " + task); Thread.Sleep (1000); // 模拟执行工作... } else _wh.WaitOne(); // 没有任务了,等待信号 } } } //为保证线程安全,我们使用了一个锁来保护对Queue<string>的访问。在Dispose方法中,我们也显式关闭了等待句柄,因为在程序生命周期中,有可能会创建和销毁许多这个类的实例。 下边是测试这个队列的主方法: static void Main() { using (ProducerConsumerQueue q = new ProducerConsumerQueue()) { q.EnqueueTask ("Hello"); for (int i = 0; i < 10; i++) q.EnqueueTask ("Say " + i); q.EnqueueTask ("Goodbye!"); } // 使用 using 语句结束时会调用 q 的 Dispose 方法 // 该方法向队列中插入一个 null 的任务,并等待消费者完成退出。 } 输出结果: Performing task: Hello Performing task: Say 1 Performing task: Say 2 Performing task: Say 3 ... ... Performing task: Say 9 Goodbye!