实现一个双缓冲队列(二)
上一篇(http://www.cnblogs.com/cqgis/p/6403262.html)实现了一个双缓冲队列的例子,我们把消费者的方法直接写到了队例里,为了达到更好的复用,这一篇分享一个封装的泛型类
/// <summary>
/// 双缓冲队列
/// </summary>
/// <typeparam name="T"></typeparam>
public class DoubleBufferedQueue<T> : IDisposable
{
private readonly int _millisecond;
/// <summary>
///
/// </summary>
private readonly Queue<T> _queue1 = new Queue<T>();
private readonly Queue<T> _queue2 = new Queue<T>();
private readonly ManualResetEvent _equeueLock = new ManualResetEvent(true);
private readonly ManualResetEvent _dequeuelock = new ManualResetEvent(false);
private readonly AutoResetEvent _autoReset = new AutoResetEvent(true);
private volatile Queue<T> _currentQueue;
private readonly BackgroundWorker _backgroundWorker;
/// <summary>
/// 双缓冲队列
/// </summary>
/// <param name="millisecond">消费者线程处理一批后,需要延时的时间,实现定时间隔操作</param>
public DoubleBufferedQueue(int millisecond = 0)
{
_millisecond = millisecond;
_currentQueue = _queue1;
_backgroundWorker = new BackgroundWorker();
_backgroundWorker.DoWork += BackgroundWorker_DoWork;
_backgroundWorker.RunWorkerAsync();
}
/// <summary>
/// 消息者处理方法
/// </summary>
public Action<Queue<T>> ConsumerAction { get; set; }
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
var readQueue = this.GetDequeue();
ConsumerAction?.Invoke(readQueue);
if (_millisecond > 0)
Thread.Sleep(TimeSpan.FromMilliseconds(_millisecond));
}
// ReSharper disable once FunctionNeverReturns
}
public void Equeue(T item, Action<T> action = null)
{
this._dequeuelock.WaitOne();
this._equeueLock.Reset();
_currentQueue.Enqueue(item);
action?.Invoke(item);
_equeueLock.Set();
_autoReset.Set();
}
private Queue<T> GetDequeue()
{
this._autoReset.WaitOne(); //这个信号量是保证在没有成员入队列的时间,不进行其它操作
this._dequeuelock.Reset(); //注意两把锁的顺序,不然会造成死锁的问题
this._equeueLock.WaitOne();
var readQueue = _currentQueue;
_currentQueue = (_currentQueue == _queue1) ? _queue2 : _queue1;
this._dequeuelock.Set();
return readQueue;
}
public void Dispose()
{
_dequeuelock.Reset();
ConsumerAction?.Invoke(_queue1);
ConsumerAction?.Invoke(_queue2);
_backgroundWorker?.Dispose();
}
}
在调用的时候,指定ConsumerAction即可。
浙公网安备 33010602011771号