简体   繁体   English

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

[英]How to check the blocking state of AutoResetEvent or ManualResetEvent in C#?

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

An EventWaitHandle doesn't have a "blocking state". EventWaitHandle没有“阻塞状态”。 It is set or reset, nothing else. 它被设置或重置,没有别的。 And no, you cannot check that any other way than by calling WaitOne(). 不,你不能通过调用WaitOne()来检查其他任何方式。

You can pass a 0 for the time-out argument to avoid blocking. 您可以为超时参数传递0以避免阻塞。 That's often a very bad idea because it says nothing about the state of the event after the WaitOne() call returns. 这通常是一个非常糟糕的主意,因为在WaitOne()调用返回后它没有说明事件的状态。 It might have changed a nanosecond after that. 之后它可能已经改变了一纳秒。 This causes a very nasty kind of bug called "threading race". 这会导致一种非常讨厌的错误,称为“穿线竞赛”。 A Heisenbug. 一个Heisenbug。

Use 使用

public virtual bool WaitOne(
    TimeSpan timeout
)

with timeout 0. According to MSDN it will return the state of the WaitHandle immediately. 超时0.根据MSDN,它将立即返回WaitHandle的状态。

I had the same question, really just building a demo app. 我有同样的问题,真的只是构建一个演示应用程序。 (Newbie to EventWaitHandle.) (EventWaitHandle新手。)

This is how I solved the problem (in VB.NET): 这就是我解决问题的方法(在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

At any point that you need to check the blocking status of that instance, just do this: 在任何时候您需要检查该实例的阻止状态,只需执行以下操作:

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

So, no, you can't REALLY figure out what is blocked before calling WaitOne(), but you can run it in an ASync way that prevents it from seizing your main thread. 所以,不,你不能真正弄清楚在调用WaitOne()之前阻塞了什么,但你可以用ASync方式运行它,以防止它占用你的主线程。 You could probably reduce the sleep value quite a bit as well, if that is too long to wait. 如果等待的时间太长,你可能也会降低睡眠值。

Obviously, if you need to check on multiple blocks, the function gets a tad bit more complex (or you have to create more of them), but this demonstrates the basic principle. 显然,如果你需要检查多个块,那么函数会变得有点复杂(或者你必须创建更多它们),但这证明了基本原理。 I also tested this as an AutoReset, and it doesn't work quite as well. 我还测试了它作为AutoReset,并且它不能很好地工作。 Because the handler is in autoreset, once I call the method to check the block, it resets and blocks my other thread. 因为处理程序是自动复位的,所以一旦我调用方法来检查块,它就会重置并阻塞我的其他线程。 So if you can run in ManualReset, this could work for you. 因此,如果您可以在ManualReset中运行,这可能对您有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM