如何在C#中检查AutoResetEvent或ManualResetEvent的阻塞状态?

时间:2012-02-17 09:56:42

标签: c# synchronization thread-safety block

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

3 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:1)

使用

public virtual bool WaitOne(
    TimeSpan timeout
)

超时0.根据MSDN,它将立即返回WaitHandle的状态。

答案 2 :(得分: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()之前真正弄清楚阻塞了什么,但你可以用ASync方式运行它,以防止它占用你的主线程。如果等待的时间太长,你可能会减少睡眠值。

显然,如果你需要检查多个块,那么函数会变得有点复杂(或者你必须创建更多它们),但这证明了基本原理。我还测试了它作为AutoReset,并且它不能很好地工作。因为处理程序是自动复位的,所以一旦我调用方法来检查块,它就会重置并阻塞我的其他线程。因此,如果您可以在ManualReset中运行,这可能对您有用。