我如何子类化WaitHandle

本文关键字:WaitHandle 子类 何子类 | 更新日期: 2023-09-27 18:16:33

有可能吗?

例如,假设我想实现一个可等待队列,如下所示:

public class WaitableQueue : WaitHandle {
    public WaitableQueue() {
      q = new Queue();
    }
    public void Enqueue(Object Arg) {
      lock(this) {
        q.Enqueue(Arg);
        // set the waithandle here (how?)
      }
    }
    public Type Dequeue() {
      lock(this) {
        if(q.Count == 1)
        // reset the waithandle here (how?)
        return q.Dequeue();
      }
    }
    Queue q;
  }

我如何子类化WaitHandle

重要的是要记住您必须设置SafeWaitHandle属性。

从MSDN:

当你从WaitHandle派生时,使用SafeWaitHandle属性来存储本机句柄操作系统句柄。你不需要这么做覆盖受保护的Dispose方法,除非使用附加的非托管资源。

我是这样做的。

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;
        }
    }
}

当这样做时,Enqueue的行为像Set方法,Dequeue的行为像Reset方法。基本上这就像一个计数事件,非零是有信号的,零是没有信号的。在这种情况下,队列正在进行计数,并且它恰好也保存数据。

我知道你在问关于WaitHandle子类化的问题,但是这个特定的数据结构不仅仅是一个练习。它在某些情况下是有用的。但是,我不会将其称为可等待队列,因为这意味着,至少对我来说,Dequeue操作将在队列为空时阻塞。显然,在这个特定的实现中不会发生这种情况。

EventWaitHandle类有一个Set和Reset方法,所以你可以从它继承而不是WaitHandle。

然而,我想说的是,对于所提供的示例,我不认为这将是一个很好的实现,因为SafeWaitableQueue类现在有两个不同的角色:队列和等待句柄。

但是,如果你有其他的想法,你需要实现自己的等待句柄,我建议尝试从EventWaitHandle继承。

这不是一个很好的解决方案,因为Set和Reset方法是公开暴露的,这意味着你的SafeWaitableQueue类的消费者也可以调用Set和Reset,可能导致一些明显un安全的行为。

我将创建一个类来聚合Queue和WaitHandle,所以:

public class WaitableQueue<T>
{
    private Queue<T> _queue;
    private WaitHandle _waitHandle;
    public WaitableQueue()
    {
        _queue = new Queue<T>();
        _waitHandle = new WaitHandle();
    }
    public void Enqueue(T Arg) {
      lock(this) {
        _queue.Enqueue(Arg);
        _waitHandle.Set();
      }
    }
    ...
}

我认为这不是继承的好用法。你的对象一个队列,而使用一个等待句柄来提供线程安全,所以你不应该从WaitHandle派生。