Reputation: 8276
I am currently using the ManualResetEvent for a single thread to wait for multiple thread to add something to the queue of a thread manager. If the thread manager receives a signal using manual reset event, it will dequeue the added item and do further processing. My only problem is that if there are multiple set are triggered, then the other queue item would not be processed. (see point 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();
}
My workaround on here is to add a queue size condition on point A. Is there another way to perform this to avoid deadlock?
Note: The usual scenario given on example on the use of ManualResetEvent is there are multiple thread waiting(ManualResetEvent.Wait) for an event on a single thread, but here multiple thread triggers(ManualResetEvent.Set) the event. Is there other class that is used for this scenario?
Upvotes: 0
Views: 919
Reputation: 24857
Dump the manual reset event now. Don't use any kind of event for this. Use a semaphore and a lock. In the push method, lock on the queue, push the object onto the queue, exit the lock statement block and then signal the semaphore. In the pop method, wait on the semaphore, then lock on the queue, pop off the object and exit the lock statement block.
That's if you really want to homebrew producer-consumer queues. If you want a queue that already works, look at the BlockingCollection classes.
Upvotes: 1
Reputation: 5085
You could process all items in the queue, if any, then wait for event to be signalled.
When event is signalled, reset it immediately.
If event is then signalled after you have processed last item in queue, the worst that will happen is you will check the queue and it will be empty.
while (IsThreadRunning)
{
while ( DataQueue.Count > 0 )
{
DataQueue.Dequeue();
}
ResetEvent.WaitOne();
ResetEvent.Reset();
}
Upvotes: 1