使用AutoResetEvent信号实现生产者消费者队列:
主程序作为生产者,添加工作任务;
工作者线程作为消费者,处理工作队列中的任务。
说明:
AutoResetEvent信号:使线程收到信号时,解除阻塞一次。
代码:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//使用using:在using作用域结束时调用ProducerConsumerQueue的析构方法dispose,释放资源
using (ProducerConsumerQueue _pcq = new ProducerConsumerQueue())
{
_pcq.EnQueue("开始工作");
for (int i = 0; i < 10; i++)
{
_pcq.EnQueue("Work item:" + i);
}
_pcq.EnQueue("工作结束");
}
//调用ProducerConsumerQueue的析构方法dispose,释放资源
}
}
class ProducerConsumerQueue : IDisposable
{
EventWaitHandle _ewh = new AutoResetEvent(false);
Queue<string> _taskQueue = new Queue<string>();
Thread _work;
readonly object _locker = new object();//加锁,实现队列的线程安全
public ProducerConsumerQueue()
{
_work = new Thread(Work);
_work.Start();//启动工作者线程
}
/// <summary>
/// 任务入队列
/// </summary>
/// <param name="task">任务</param>
public void EnQueue(string task)
{
lock (_locker)//加锁,实现线程安全
{
_taskQueue.Enqueue(task);
}
_ewh.Set();//信号AutoResetEvent:允许线程执行一次
}
void Work()
{
while (true)
{
string task = null;
if (_taskQueue.Count>0)
{
lock (_locker)//加锁,实现线程安全
{
task = _taskQueue.Dequeue();//出队列
}
if (task == null) return;//队列添加一条NULL的任务,表示任务执行完成,退出
}
if (task != null)
{
Console.WriteLine("Performtask:" + task);
Thread.Sleep(1000);//模拟任务执行
}
else
_ewh.WaitOne();//没有任务了,等待信号
}
}
public void Dispose()
{
EnQueue(null);//结束工作
_work.Join();//等待工作者线程结束
_ewh.Close();//释放等待句柄
}
}
}