如何继承WaitHandle?

问题描述:

是否有可能(以有意义的方式)?如何继承WaitHandle?

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

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

如果可能的话,你是如何使用它的? –

+0

[C#中的队列和等待句柄]的可能重复(http://*.com/questions/2741042/queues-and-wait-handles-in-c-sharp) –

+0

不可以。我给出的例子恰好与关于队列的实际问题相吻合。 – schwrz

重要的是要记住,您必须设置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操作将被阻止。显然这不是在这个特定的实现中会发生什么。

+0

您始终可以拥有Dequeue(bool Blocking),但在任何情况下,这都是我一直在寻找的解决方案。我希望能够保护Set和Reset或者受保护的ctor有一个参数,就像在WaitHandle(SafeWaitHandle Handle)中一样。我找不到这些,那就是把我扔掉的东西(可惜我也错过了你引用的MSDN位)。我的问题确实是一般性的,但它确实来自现实生活场景,您的解决方案将得到很好的利用。谢谢! – schwrz

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

+0

我并不是专门寻求实现一个等待队列。这只是一个例子。我在问WaitHandle是否可以用有意义的方式派生(参见我的原文) – schwrz

+1

它是一个抽象基类,所以它是由.NET框架中的所有具体同步类以有意义的方式派生的(Mutex ,信号量等)。我相信你可以使用它来开发.NET以外不支持的另一种类型的同步原语。 – jlew

+0

你会怎么做呢?在我看来,无法使用.NET基元来完成,因为您无法控制继承的句柄。 – schwrz

我想创建它汇集双方队列,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(); 
     } 
    } 
    ... 
} 
+0

当然,但后来我无法:WaitHandle.WaitAny(q1,q2)... – schwrz

+1

也许_waitHandle应该作为只读公共属性公开并且/或者应该有构造函数重载,它接受WaitHandle作为参数。这样,您可以使用这个WaitableQueue类,如果您需要执行WaitHandle.WaitAny(q1,q1,...),那么您仍然可以这样做,因为您可以访问队列正在使用的WaitHandle。 –

+1

如果您将_waitHandle作为公共'get'属性 –

的的EventWaitHandle类有设置和重置的方法,所以你可以从替代的WaitHandle的继承。

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

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

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

+0

我认为EventWaitHandle会像AutoResetEvent和ManualResetEvent一样被密封。正如您正确指出的那样,曝光问题是一个问题。 – schwrz