|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Monitor.Wait problembooks I got a problem that is not mentioned anyware. Let's say thread1 does following: Monitor.Enter(o); try { Do X; Monitor.Wait(o); Do.Y; } finally { Monitor.Exit(o); } Thread2 does: Monitor.Enter(o); try { Do A; Monitor.Pulse(o); Do.B; } finally { Monitor.Exit(o); } On my dual core processor it happens sometimes that Thread2 ends before Thread 1 starts, though they are started in order: Thread1, Thread2!! And there is the problem: At the moment Thread1 calls Monitor.Wait, thread2 is already finished, so there is no thread that can call Pulse So, Thread1 blocks forever. QUESTION: Why does Monitor.Wait not acquire the lock back if no other thread holds the lock. How can I detect this situation and avoid it in an elegant way? Regards Liviu Liviu Ursu <livi***@gmail.com> wrote:
> Hi, I am relatively new to NET Threading and learning from net examples and <snip>> books I got a problem that is not mentioned anyware. (You should use the lock statement to make things more readable, by the way.) > On my dual core processor it happens sometimes that Thread2 ends before Because it waits for the monitor to be pulsed. If another thread is > Thread 1 starts, though they are started in order: Thread1, Thread2!! > And there is the problem: > > At the moment Thread1 calls Monitor.Wait, thread2 is already finished, so > there is no thread that can call Pulse > So, Thread1 blocks forever. > > QUESTION: Why does Monitor.Wait not acquire the lock back if no other > thread holds the lock. holding the lock, the thread calling Wait wouldn't be able to hold the lock at the same time, which means the call to Wait would throw an exception anyway. > How can I detect this situation and avoid it in an elegant way? Use a piece of shared data (a boolean, a counter, whatever) to indicate what's going on. It's hard to give more specifics without knowing what you're trying to achieve. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too Hi,
Thanx. But exactly that is the problem. At the time Thread1 calls Monitor.Wait, there is no other thread. It is the only thread running except the GUI.. I could have left Thread2 away, and say I have just one thread. Intuitively i don't see any reason Monitor.Wait has to wait if it has nothing to wait for :-) Show quote "Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message news:MPG.1ea8b7b4a2e0c02498d0b1@msnews.microsoft.com... > Liviu Ursu <livi***@gmail.com> wrote: >> Hi, I am relatively new to NET Threading and learning from net examples >> and >> books I got a problem that is not mentioned anyware. > > <snip> > > (You should use the lock statement to make things more readable, by the > way.) > >> On my dual core processor it happens sometimes that Thread2 ends before >> Thread 1 starts, though they are started in order: Thread1, Thread2!! >> And there is the problem: >> >> At the moment Thread1 calls Monitor.Wait, thread2 is already finished, >> so >> there is no thread that can call Pulse >> So, Thread1 blocks forever. >> >> QUESTION: Why does Monitor.Wait not acquire the lock back if no other >> thread holds the lock. > > Because it waits for the monitor to be pulsed. If another thread is > holding the lock, the thread calling Wait wouldn't be able to hold the > lock at the same time, which means the call to Wait would throw an > exception anyway. > >> How can I detect this situation and avoid it in an elegant way? > > Use a piece of shared data (a boolean, a counter, whatever) to indicate > what's going on. It's hard to give more specifics without knowing what > you're trying to achieve. > > -- > Jon Skeet - <sk***@pobox.com> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > If replying to the group, please do not mail me too Where I see the problem:
No one can know for sure that another Thread will call Pulse after I call Wait. For simple logic, that maybe the case. For complex programs.... All examples i saw on the net are just wrong, and they may block forever run on a multiprocessor machine at least. I can reproduce on my computer a crazy bug in BackgroundWorker from vsnet 2005, just that the progress method is called in random order 100% 20% 50%, not in the order actually intended. Show quote "Liviu Ursu" <livi***@gmail.com> wrote in message news:OPnnZvzXGHA.1348@TK2MSFTNGP05.phx.gbl... > Hi, > > Thanx. But exactly that is the problem. > At the time Thread1 calls Monitor.Wait, there is no other thread. It is > the only thread running except the GUI.. > I could have left Thread2 away, and say I have just one thread. > > Intuitively i don't see any reason Monitor.Wait has to wait if it has > nothing to wait for :-) > > "Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message > news:MPG.1ea8b7b4a2e0c02498d0b1@msnews.microsoft.com... >> Liviu Ursu <livi***@gmail.com> wrote: >>> Hi, I am relatively new to NET Threading and learning from net examples >>> and >>> books I got a problem that is not mentioned anyware. >> >> <snip> >> >> (You should use the lock statement to make things more readable, by the >> way.) >> >>> On my dual core processor it happens sometimes that Thread2 ends before >>> Thread 1 starts, though they are started in order: Thread1, Thread2!! >>> And there is the problem: >>> >>> At the moment Thread1 calls Monitor.Wait, thread2 is already finished, >>> so >>> there is no thread that can call Pulse >>> So, Thread1 blocks forever. >>> >>> QUESTION: Why does Monitor.Wait not acquire the lock back if no other >>> thread holds the lock. >> >> Because it waits for the monitor to be pulsed. If another thread is >> holding the lock, the thread calling Wait wouldn't be able to hold the >> lock at the same time, which means the call to Wait would throw an >> exception anyway. >> >>> How can I detect this situation and avoid it in an elegant way? >> >> Use a piece of shared data (a boolean, a counter, whatever) to indicate >> what's going on. It's hard to give more specifics without knowing what >> you're trying to achieve. >> >> -- >> Jon Skeet - <sk***@pobox.com> >> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet >> If replying to the group, please do not mail me too > > Liviu Ursu <livi***@gmail.com> wrote:
> Where I see the problem: They will only block forever if you let them wait when there's nothing > > No one can know for sure that another Thread will call Pulse after I call > Wait. For simple logic, that maybe the case. > For complex programs.... > All examples i saw on the net are just wrong, and they may block forever run > on a multiprocessor machine at least. to wait for. In most cases, you would have a "while" loop which would check whether there's something to wait for before waiting. > I can reproduce on my computer a crazy bug in BackgroundWorker from vsnet That sounds like it's more likely to be a bug in the code *using* > 2005, just that the progress method is called in random order 100% 20% 50%, > not in the order actually intended. BackgroundWorker than in BackgroundWorker itself. Could you post a short but complete program which demonstrates the problem? See http://www.pobox.com/~skeet/csharp/complete.html for details of what I mean by that. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too Moving to BackGroundWorker :-)
The code is the simplest code possible: for i:= 1 to 100 ProgressChanged(...) As I told, on my dualcore it is possible that although threads t1 and t2 are started exactly in this order in code, actually they start in reverse order: t2, t1 An explanation exists for the behaviour of Bgw, the progresschanged event is called asynchronously, queued to a ThreadPool thread, so there is really no guarantee of the order. What is wrong, is that in MSDN there is no comment on this. Most folks that have a single processor machine never face this issue until delevering binaries to client's servers ;-( Show quote "Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message news:MPG.1ea95e90f6518c4598d0b8@msnews.microsoft.com... > Liviu Ursu <livi***@gmail.com> wrote: >> Where I see the problem: >> >> No one can know for sure that another Thread will call Pulse after I call >> Wait. For simple logic, that maybe the case. >> For complex programs.... >> All examples i saw on the net are just wrong, and they may block forever >> run >> on a multiprocessor machine at least. > > They will only block forever if you let them wait when there's nothing > to wait for. In most cases, you would have a "while" loop which would > check whether there's something to wait for before waiting. > >> I can reproduce on my computer a crazy bug in BackgroundWorker from vsnet >> 2005, just that the progress method is called in random order 100% 20% >> 50%, >> not in the order actually intended. > > That sounds like it's more likely to be a bug in the code *using* > BackgroundWorker than in BackgroundWorker itself. > > Could you post a short but complete program which demonstrates the > problem? > > See http://www.pobox.com/~skeet/csharp/complete.html for details of > what I mean by that. > > -- > Jon Skeet - <sk***@pobox.com> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > If replying to the group, please do not mail me too Liviu Uba <u**@totalsoft.ro> wrote:
> Moving to BackGroundWorker :-) <snip>> The code is the simplest code possible: That's not a complete program, which is what I requested. > for i:= 1 to 100 Yes, but that's a different issue.> ProgressChanged(...) > > As I told, on my dualcore it is possible that although threads t1 and t2 are > started exactly in this order in code, actually they start in reverse order: > t2, t1 > An explanation exists for the behaviour of Bgw, the progresschanged event is When I've seen a short but complete program which demonstrates the > called asynchronously, queued to a ThreadPool thread, so there is really no > guarantee of the order. What is wrong, is that in MSDN there is no comment > on this. Most folks that have a single processor machine never face this > issue until delevering binaries to client's servers ;-( problem, I'll be able to comment better. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too |
|||||||||||||||||||||||