Re: Queue object with strange behaviour??

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Marc,

This totally works! Perfectly! We were also having data loss in our logs
and this has totally fixed it including maintaining the correct order of the
log entries.

I have been reading Jon's page on threading. I am going to read more later
on this afternoon when I have more time. That is very important stuff as you
mentioned. I may have to go back in some of my other code and fix some
things.

On behalf of the IT team here, we thank you for taking the time to help us!!
This fix is like gold to us. Let me know if there is ever something I can
do for you.

Thanks,

Rob K

"Marc Gravell" wrote:

first... DO NOT check the Count whle you don't own the lock; this WILL
break... as the film goes "maybe not today, maybe not tomorrow, but
some day, soon, and for the rest of your life". That's the joy of
threading. Alternative suggested below.

// note: terminate should be a "volatile bool"
bool continue = true;
while(continue) {
T item;
lock(LoggingQueue) { // obtain exclusive access
if(LoggingQueue.Count==0) { // I wouldn't worry about -ve myself...
up to you
if(terminate) { // shut down requested
continue = false; // queue is empty, so exit loop
} else { // queue is empty; wait for work
Monitor.Wait(LoggingQueue); // relinquish lock, wait for a
kick, and reaquire
continue; // start loop again
}
//// etc as per my previous post, with logging near the bottom (outside
of the lock)

Note: I advise you to go a bit closer to my sample code; otherwise
(with your code below), if a queue has built up, it will need to log
all of it before more can be added. My way only processes one item per
lock, *and* it processes that item *outside* of the lock, which means
that adding new items is not bound by IO.

Also; the ==1 was for a reason; as it stands, you are doing unnecessary
Pulse()s; we know that we only Wait() if the queue is empty, i.e.
Count==0; this only happens if, after adding, the Count is 1. If the
Count is 7, we can say for sure that the logging thread is not
Wait()ing, but rather is simply patiently waiting on the lock that we
hold. No need for a Pulse().

Since the two threads are now isolated, I would also remove the
Sleep(), but again, that is up to you.

I can't really explain (in a short post) all of why this works. Threads
are tricky. You should really read Jon's pages end to end. Then read it
again ;-p

http://www.yoda.arachsys.com/csharp/threads/

Marc


.



Relevant Pages

  • Re: synchronizations of threads
    ... To answer your immediate question, it's not the lock using workLock that's superfluous, it's the lock using workQueue. ... As has been discussed elsewhere, including in Jon Skeet's web article on threading, using a privately allocated instance of Object for a lock is preferable to using the object that actually needs the synchronized access, because doing so ensures that only that particular code is locking on that particular object. ... I am surprised to see the non-generic Queue class being used, but more significantly the use of the "stop" variable to signal a shutdown rather than just communicating through the queue, which leads to the two-second timeout, another questionable design choice, and the fact that the workLock lock is held during the entire execution of the worker delegate, these are all bad problems IMHO. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Multithreaded queue with wait event
    ... queue and signals the event, only one thread will receive the signal while ... empty to empty, it changes the state of the event as well. ... Acquire lock ... you can keep a count of waiters and skip ...
    (comp.programming.threads)
  • Re: std::queue empty() is thread safe?
    ... Consider the situation where queue isn't empty on "if" ... > but gets empty on "lock". ... performance loss is so minimal that we shouldn't even consider it. ...
    (microsoft.public.dotnet.languages.vc)
  • Re: try/catch on dequeue is way slower than my own lock
    ... You need the lock anyway if there is item, ... Couple ways to go on empty. ... avoid the error condition and get explicit condition if queue is really ... was 100x slower than doing my own empty-check before dequeue. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Python 2.6s multiprocessing lock not working on second use?
    ... migrating a threading code, and found out the locking code is not ... trying to get the lock and releasing it after waiting 0.2 seconds ... I just tested it without the queue and ...
    (comp.lang.python)