首页 > 代码库 > 使用事件等待句柄EventWaitHandler 实现生产者、消费者队列

使用事件等待句柄EventWaitHandler 实现生产者、消费者队列

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!

 

使用事件等待句柄EventWaitHandler 实现生产者、消费者队列