【问题标题】:Is ManualResetEvent size checking sufficient for waiting for multiple thread?ManualResetEvent 大小检查是否足以等待多个线程?
【发布时间】:2012-02-28 09:43:25
【问题描述】:

我目前正在为单个线程使用 ManualResetEvent 来等待多个线程将某些内容添加到线程管理器的队列中。如果线程管理器使用手动重置事件接收到信号,它将使添加的项目出列并进行进一步处理。我唯一的问题是,如果触发了多个集合,则不会处理其他队列项。 (见B点)

while (IsThreadRunning)
{
    // A: My workaround is to check if queue has item, if not then wait for other thread to set the event
    if (DataQueue.Count <= 0)
    {
        ResetEvent.WaitOne();
    }

    // B: At this point two thread added item to the queue and did ResetEvent.Set() twice.
    if (DataQueue.Count > 0)
    {
        DataQueue.Dequeue();
    }

    // Reset the event to avoid processor hog
    ResetEvent.Reset();
}

我的解决方法是在 A 点 上添加队列大小条件。 有没有其他方法可以避免死锁?

注意:在使用 ManualResetEvent 的示例中给出的通常场景是单个线程上有多个线程等待(ManualResetEvent.Wait)事件,但这里是多个线程触发(ManualResetEvent.Set)事件。是否有其他类用于此场景?

【问题讨论】:

  • 为什么不把你的第二个换成一段时间呢?

标签: c# multithreading manualresetevent


【解决方案1】:

您可以处理队列中的所有项目(如果有),然后等待事件发出信号。

当事件发出信号时,立即将其重置。

如果在您处理完队列中的最后一项后发出事件信号,那么最糟糕的情况是您将检查队列并且它会是空的。

while (IsThreadRunning)
{
  while ( DataQueue.Count > 0 )
  {
    DataQueue.Dequeue();
  }
  ResetEvent.WaitOne();
  ResetEvent.Reset();
}

【讨论】:

    【解决方案2】:

    现在转储手动重置事件。不要为此使用任何类型的事件。使用信号量和锁。在 push 方法中,锁定队列,将对象推入队列,退出锁定语句块,然后发出信号量。在 pop 方法中,等待信号量,然后锁定队列,弹出对象并退出锁定语句块。

    如果你真的想自制生产者-消费者队列。如果您想要一个已经可以工作的队列,请查看 BlockingCollection 类。

    【讨论】:

    • @Nap - 没有。使用队列锁和信号量(如果队列有界,则使用 2 个信号量)是实现生产者-消费者队列的“计算机科学 101”方法。我不知道开发人员从哪里得到使用事件而不是信号量的想法来实现需要具有计数器的同步机制的东西!
    猜你喜欢
    • 2017-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多