我怎样才能将WaitHandle子类化?

时间:2011-12-02 13:24:02

标签: c# multithreading

是否有可能(以有意义的方式)?

例如,假设我想按如下方式实现一个可等待的队列:

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

4 个答案:

答案 0 :(得分:7)

要记住的重要一点是,您必须设置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操作将在队列为空时阻塞。显然,这不是在这个特定实施中会发生的事情。

答案 1 :(得分:3)

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

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

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

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

答案 2 :(得分:1)

我创建了一个聚合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();
      }
    }
    ...
}

答案 3 :(得分:0)

我认为这不是对继承的好用。您的对象队列,而使用等待句柄来提供线程安全性,因此您不应该从WaitHandle派生。