|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
SynchronizationAttribute and Monitor.Wait deadlockfor. The one named exitContext so I started playing with the synchronize attribute to find out how it all works. I'm puzzled at why this blocks until it times out. What is supposed to happen is the consumer thread is started and waits for a producer to signal that something is ready. This behavior is true if reEntrant == true. What actually happens is that the consumer never releases its context lock on the object so the producer is unable to enter the object whilst the consumer is waiting. So what is the difference? Why can't Monitor.Wait release its lock on the context unless reEntrant == true? class Program { public static void Main() { Tester test = new Tester(); Thread t1 = new Thread(new ThreadStart(test.Consume)); Thread t2 = new Thread(new ThreadStart(test.Produce)); t1.Start(); //ensure our consumer gets a lock and waits before starting the producer Thread.Sleep(10); t2.Start(); t1.Join(); t2.Join(); Console.ReadKey(true); } } //note: that reEntrant == false, if it's set to true there is no problem [Synchronization(SynchronizationAttribute.REQUIRES_NEW, false)] public class Tester : ContextBoundObject { private object resource_lock = new object(); //this method will not run on the second thread until the consumer times out and the first thread //leaves the class (and thus the context). public void Produce() { Console.WriteLine("Tester begin produce: ThreadId = " + Thread.CurrentThread.ManagedThreadId); lock (resource_lock) { //just pretend we are doing something then signal the consumer Thread.Sleep(1000); Monitor.Pulse(resource_lock); } Console.WriteLine("Tester end produce: ThreadId = " + Thread.CurrentThread.ManagedThreadId); } public void Consume() { Console.WriteLine("Tester begin consume: ThreadId = " + Thread.CurrentThread.ManagedThreadId); lock (resource_lock) { //This will block indefinitely without the timeout, but should this not release the context? if (Monitor.Wait(resource_lock, 5000, true)) { Console.WriteLine("Tester, Item consumed"); } else { Console.WriteLine("Tester, TIMED OUT"); } } Console.WriteLine("Tester end consume: ThreadId = " + Thread.CurrentThread.ManagedThreadId); } } OUTPUT: Tester begin consume: ThreadId = 4 Tester, TIMED OUT Tester end consume: ThreadId = 4 Tester begin produce: ThreadId = 5 Tester end produce: ThreadId = 5 EXPECTED OUTPUT: (this behavior is exibited if reEntrant == true) Tester begin consume: ThreadId = 4 Tester begin produce: ThreadId = 5 Tester end produce: ThreadId = 5 Tester, Item consumed Tester end consume: ThreadId = 4 |
|||||||||||||||||||||||