我目前正在使用ManualResetEvent为单个线程等待多个线程将某些东西添加到线程管理器的队列中。如果线程管理器使用手动重置事件接收到信号,它将使添加的项目出列并进行进一步处理。我唯一的问题是,如果触发了多个set,则不会处理另一个队列项。 (见 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)事件。是否有其他类用于此场景?
答案 0 :(得分:1)
您可以处理队列中的所有项目(如果有),然后等待事件发出信号。
发出事件信号后,立即重置。
如果在处理完队列中的最后一项后再发出事件信号,那么最糟糕的情况是你将检查队列并且它将是空的。
while (IsThreadRunning)
{
while ( DataQueue.Count > 0 )
{
DataQueue.Dequeue();
}
ResetEvent.WaitOne();
ResetEvent.Reset();
}
答案 1 :(得分:1)
立即转储手动重置事件。不要为此使用任何类型的事件。使用信号量和锁。在push方法中,锁定队列,将对象推入队列,退出lock语句块,然后发出信号量信号。在pop方法中,等待信号量,然后锁定队列,弹出对象并退出锁定语句块。
如果您真的想要自制生产者 - 消费者队列,那就是这样。如果您想要一个已经有效的队列,请查看BlockingCollection类。