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

发布于 2025-01-06 17:21:51 字数 109 浏览 0 评论 0原文

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

Is it possible to check the blocking state for C# System.Threading.AutoResetEvent or
System.Threading.ManualResetEvent before calling WaitOne() ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

如果没有 2025-01-13 17:21:51

EventWaitHandle 没有“阻塞状态”。它被设置或重置,没有别的。不,除了调用 WaitOne() 之外,您无法通过任何其他方式进行检查。

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

An EventWaitHandle doesn't have a "blocking state". It is set or reset, nothing else. And no, you cannot check that any other way than by calling WaitOne().

You can pass a 0 for the time-out argument to avoid blocking. That's often a very bad idea because it says nothing about the state of the event after the WaitOne() call returns. It might have changed a nanosecond after that. This causes a very nasty kind of bug called "threading race". A Heisenbug.

软的没边 2025-01-13 17:21:51

使用

public virtual bool WaitOne(
    TimeSpan timeout
)

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

Use

public virtual bool WaitOne(
    TimeSpan timeout
)

with timeout 0. According to MSDN it will return the state of the WaitHandle immediately.

泡沫很甜 2025-01-13 17:21:51

我有同样的问题,实际上只是构建一个演示应用程序。 (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() 之前被阻止的内容,但您可以以异步方式运行它,以防止它占用主线程。如果等待时间太长,您也可以稍微降低睡眠值。

显然,如果您需要检查多个块,该函数会变得有点复杂(或者您必须创建更多块),但这演示了基本原理。我还测试了它作为自动重置,但效果不太好。因为处理程序处于自动重置状态,所以一旦我调用该方法来检查块,它就会重置并阻止我的其他线程。因此,如果您可以在 ManualReset 中运行,这可能对您有用。

I had the same question, really just building a demo app. (Newbie to EventWaitHandle.)

This is how I solved the problem (in 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. 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. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文