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

6

在调用WaitOne()方法之前,能否检查C# System.Threading.AutoResetEvent或System.Threading.ManualResetEvent的阻塞状态呢?


使用反射。你的实际问题是什么? - Matt Ellen
我正在开发一个与特殊硬件通信的UDP客户端。我不得不实现一个阻塞代码来同步通信。事情必须快速运行,所以我不能在WaitOne()之前放置断点。我有4个AutoResetEvents。当通信阻塞时,我想知道是哪一个。我知道写入控制台将显示位置,但写入需要时间,在这样关键的环境中,我不能浪费时间。 - Patrik
3个回答

6
一个EventWaitHandle没有“阻塞状态”。它只能设置或重置,没有其他状态。而且,你不能通过任何其他方式检查它,只能调用WaitOne()方法来检查。
你可以传递0作为超时参数以避免阻塞。这通常是一个非常糟糕的想法,因为它不能说明WaitOne()方法返回后事件的状态。它可能在那之后的纳秒级别发生了变化。这会导致一种非常恶劣的错误,称为“线程竞争”或“海森堡式Bug”。

我知道EventWaitHandle没有阻塞状态,但如果它没有被信号通知,它会阻塞当前线程的执行。在同一个while循环中,我有4个EventWaitHandles在一个线程中工作。其中一些必须有条件地阻塞线程。我想从其他事件中了解这4个句柄中哪些被阻塞了。我发现我必须添加一些与句柄相关联的bool变量来获取这些信息。 - Patrik

1

使用

public virtual bool WaitOne(
    TimeSpan timeout
)

设定超时时间为0。根据MSDN,它将立即返回WaitHandle的状态。


对此有一点说明。我认为在AutoResetEvent上使用WaitOne(0)可能会重置它。如果已经被标记,你必须在WaitOne之后使用Set。但是我同意Hans关于竞态条件的观点。如果有多个线程调用了WaitOne,这可能会导致严重的错误。使用ManualResetEvent则没有问题。 - BlueM

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中运行,这可能适合你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接