Is this BlockingQueue susceptible to deadlock?
- by unforgiven3
I've been using this code as a queue that blocks on Dequeue() until an element is enqueued. I've used this code for a few years now in several projects, all with no issues... until now. I'm seeing a deadlock in some code I'm writing now, and in investigating the problem, my 'eye of suspicion' has settled on this BlockingQueue<T>. I can't prove it, so I figured I'd ask some people smarter than me to review it for potential issues. Can you guys see anything that might cause a deadlock in this code?
public class BlockingQueue<T>
{
    private readonly Queue<T> _queue;
    private readonly ManualResetEvent _event;
    /// <summary>
    /// Constructor
    /// </summary>
    public BlockingQueue()
    {
        _queue = new Queue<T>();
        _event = new ManualResetEvent(false);
    }
    /// <summary>
    /// Read-only property to get the size of the queue
    /// </summary>
    public int Size
    {
        get
        {
            int count;
            lock (_queue)
            {
                count = _queue.Count;
            }
            return count;
        }
    }
    /// <summary>
    /// Enqueues element on the queue
    /// </summary>
    /// <param name="element">Element to enqueue</param>
    public void Enqueue(T element)
    {
        lock (_queue)
        {
            _queue.Enqueue(element);
            _event.Set();
        }
    }
    /// <summary>
    /// Dequeues an element from the queue
    /// </summary>
    /// <returns>Dequeued element</returns>
    public T Dequeue()
    {
        T element;
        while (true)
        {
            if (Size == 0)
            {
                _event.Reset();
                _event.WaitOne();
            }
            lock (_queue)
            {
                if (_queue.Count == 0) continue;
                element = _queue.Dequeue();
                break;
            }
        }
        return element;
    }
    /// <summary>
    /// Clears the queue
    /// </summary>
    public void Clear()
    {
        lock (_queue)
        {
            _queue.Clear();
        }
    }
}