How Producer/Consumer msdn example works?
I don't understand how this example works http://msdn.microsoft.com/en-us/library/yy12yx1f(v=vs.80).aspx
As far as I understand Consumer doesn't read all elements produced by Producer.
Probably I don't understand correctly how AutoResetEvent
works. Does it make sense to Set
AutoreResetEvent
several times?
_newItemEvent = new AutoResetEvent(false);
_newItemEvent.Set();
_newItemEvent.Set();
_newItemEvent.Set();
_newItemEvent.Set();
This is how I understand example:
Producer:
lock (((ICollection)_queue).SyncRoot)
{
while (_queue.Count < 20)
{
_queue.Enqueue(r.Next(0,100));
_syncEvents.NewItemEvent.Set();
count++;
}
}
Consumer:
while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)
{
lock (((ICollection)_queue).SyncRoot)
{
int item = _queue.Dequeue();
}
count++;
}
Producer locks
_queue
:lock (((ICollection)_queue).SyncRoot)
Producer adds 1 element into
_queue
and setNewItemEvent
:_queue.Enqueue(r.Next(0,100)); _syncEvents.NewItemEvent.Set();
Consumer goes inside "while" loop because it received notification that
NewItemEvent
is set,NetItemEvent
is now unset because it is AutoResetEvent:while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)
Consumer "froze" at next line waiting for
_queue
lock to be released:lock (((ICollection)_queue).SyncRoot)
Producer continues add 19 more elements into
_quere
and release_queue
objectConsumer obtain a lock on
_queue
object andDequeue
one element:lock (((ICollection)_queue).SyncRoot) { int item = _queue.Dequeue(); }
Consumer executes second iteration of "while" loop because
NewItemEvent
is set,NetItemEvent
开发者_开发百科is unset now because it is AutoResetEvent:After 2 iterations Consumer waits for NewItemEvent to be set.
Result: Producer produced 20 elements.
Consumer: Dequeue
only 2 elements.
I expect Consumer to Dequeue
all 20 elements.
According to an example Consumer is Dequeue
20 elements, the question is how, why and what' wrong in my understanding of the program.
You've left out an important part of the example on the MSDN page, which is another loop around the main loop in the producer thread. The producer's job in the example is to try to keep at least 20 items in the queue.
Whenever it adds an item, the consumer is signaled, which causes it to remove an item, so there are fewer than 20 items in the queue. It doesn't matter whether this happens inside or outside the inner loop on the producer thread. The next time it reaches the while (_queue.Count < 20)
it will be false, so the producer will add at least one more item to the queue, and resignal the consumer.
Admittedly, it seems to me at least like a somewhat contrived example, since the consumer can't ever necessarily consume all entries in the queue, but it does continue to consume items as long as the producer continues to produce them.
The producer enqueues 20 elements The consumer consumes a single element, reduces the queue by one and now the queue count is 19 The producer enqueues 1 element queue is now at 20 The consumer consumes a single element, reduces the queue by one and now the queue count is 19
This continues until the exit event and leaves 19 items in the queue.
If you added a loop after the exit event fires and is handled by the consumer you could drain the rest of the queue.
This example is just trying to show you how you might handle inserting items into a queue and signal the consumer to consume. Imagine if you had 20 consumers all consuming this would allow them all to take an entry without trashing the queue.
Key take aways are: lock(_queue.SyncRoot) and Handling multiple events, one for the NewItem insert and one to exit out of the loop.
For what it is worth that MSDN article got removed...finally! The code worked alright as long as there was only a single consumer. However, if you scale up to two or more consumers then it quickly breaks down and can leave consumers live-locked in some scenarios. I, among others, have been harping about this article for quite some time now so it is nice to see that it finally went away.
Short answer...do not rely on that code for a real application.
精彩评论