The important thing to remember is that you must set the SafeWaitHandle
property.
From MSDN:
When you derive from WaitHandle, use the SafeWaitHandle property to
store your native handle operating system handle. You do not need to
override the protected Dispose method unless you use additional
unmanaged resources.
Here is how I would do this.
public class QueueWaitHandle<T> : WaitHandle
{
private Queue<T> queue = new Queue<T>();
private ManualResetEvent signal = new ManualResetEvent(false);
public QueueWaitHandle()
{
base.SafeWaitHandle = signal.SafeWaitHandle;
}
public void Enqueue(T item)
{
lock (queue)
{
queue.Enqueue(item);
signal.Set();
}
}
public T Dequeue()
{
lock (queue)
{
T item = queue.Dequeue();
if (queue.Count == 0)
{
signal.Reset();
}
return item;
}
}
}
When done this way Enqueue
acts like the Set
method and Dequeue
acts like the Reset
method. So basically this works like a counting event where non-zero is signaled and zero is unsignaled. The queue is doing the counting in this case and it just happens to also hold data.
I know you were asking about subclassing WaitHandle
in general, but this specific data structure is more than just an exercise. It can be useful in some scenarios. I would not, however, call it a waitable queue because that implies, at least to me anyway, that the Dequeue
operation will block when the queue is empty. Clearly that is not what will happen in this particular implemenation.