2012-02-17 136 views
3

是否可以在调用WaitOne()之前检查C#System.Threading.AutoResetEvent或 System.Threading.ManualResetEvent的阻塞状态?如何在C#中检查AutoResetEvent或ManualResetEvent的阻塞状态?

+0

使用反射。你真正的问题是什么? – 2012-02-17 10:09:43

+0

我正在开发与特殊硬件通信的UDP客户端。我必须实现一个阻止代码来同步通信。这些东西必须运行得很快,所以我不能在WaitOne()之前放置一个断点。我有4个AutoResetEvents。当我想知道巫婆之一的沟通块时。我知道写给控制台的信息会显示出哪里,但写作需要时间,在这样的关键环境中,我不能浪费时间。 – Patrik 2012-02-17 11:59:02

回答

4

EventWaitHandle没有“阻塞状态”。它被设置或重置,没有别的。不,你不能通过调用WaitOne()来检查其他方式。

您可以传递一个0作为超时参数以避免阻塞。这通常是一个非常糟糕的主意,因为它在WaitOne()调用返回后没有提到事件的状态。之后它可能已经改变了一个纳秒。这导致了一种非常讨厌的称为“线程竞赛”的错误。一个Heisenbug。

+0

+1,完全同意你的看法! – 2012-02-17 10:22:58

+0

我知道EventWaithandle没有阻塞状态,但是如果没有发送信号,阻塞当前线程的执行。我在同一个while循环中有4个EventWaitHandles在一个线程中工作。其中一些必须有条件地阻止线程。我想从其他事件知道这4个手柄中的哪一个被阻塞。我看到我必须添加一些链接到句柄的布尔变量来获取这些信息。 – Patrik 2012-02-17 12:06:05

1

使用

public virtual bool WaitOne(
    TimeSpan timeout 
) 

与超时0。根据MSDN它会立即返回WaitHandle中的状态。

+0

对此的评论。我期望AutoResetEvent上的WaitOne(0)可能会重置它。如果发送信号,则必须在WaitOne之后使用Set。但我必须同意汉斯关于种族条件的看法。如果您有多个称为WaitOne的线程,这可能会导致令人讨厌的错误。 ManualResetEvent没有问题。 – BlueM 2012-02-17 10:41:33

0

我有同样的问题,真的只是建立一个演示应用程序。 (新手的EventWaitHandle)

这是我如何解决(在VB.NET)问题:

Module Module1 

Dim ewh As Threading.EventWaitHandle 

Sub Main() 
    ewh = New Threading.EventWaitHandle(False, Threading.EventResetMode.ManualReset) 
    ' Do other work. 
End Sub 

Sub checkBlockStatus() 

    ewh.WaitOne() 

End Sub 

Function isEwhBlocked() As Boolean 

    Dim testEwhBlock As New Threading.Thread(AddressOf checkBlockStatus) 
    testEwhBlock.Start() 
    Threading.Thread.Sleep(1000) 
    If testEwhBlock.ThreadState <> Threading.ThreadState.Stopped Then 
    ' It's OK to use abort here because I don't care what happens to the thread. 
    testEwhBlock.Abort() 
    Return True 
    Else 
    Return False 
    End If 
    testEwhBlock = Nothing 

End Function 
End Module 

在您需要检查该实例的阻断状态,只是这样做的任何一点:

if (isEwhBlocked()) Then 
    ' This means the block is on. 
else 
    ' No block. 
End If 

所以,不,你不能真正弄清楚什么是调用了WaitOne()之前受阻,但你可以阻止它抓住你的主线程异步的方式运行。如果等待时间太长,您也可能会稍微降低睡眠值。显然,如果你需要检查多个块,函数会稍微复杂一点(或者你必须创建更多的块),但是这证明了基本原理。我也测试了它作为一个AutoReset,它不工作得很好。由于该处理程序处于自动复位状态,因此一旦我调用该方法来检查该块,它就会重置并阻止其他线程。所以,如果你可以在ManualReset中运行,这可以为你工作。