using System; using System.Collections.Generic; using System.Threading; public class Test { public static void Main() { new PulseWaitExample().Run(); } } public static class Dumper{ public static void Dump(this object o, string comment = null){ Console.WriteLine((comment != null? comment+ ": " : "" ) + o.ToString()); } } public class PulseWaitExample { int i = 0; private Queue queue= new Queue(); private volatile bool running=true; int consumed; public void Run(){ Thread tp1 = new Thread(ProducerThreadProc); Thread tp2 = new Thread(ProducerThreadProc); Thread tc1 = new Thread(ConsumerThreadProc); Thread tc2 = new Thread(ConsumerThreadProc); Thread ender = new Thread(()=> { Thread.Sleep(300); running = false; }); tp1.Start(); //tp2.Start(); tc1.Start(); //tc2.Start(); //ender.Start(); tp1.Join(); tc1.Join(); i.Dump("Produced"); consumed.Dump("consumed"); } private void ProducerThreadProc() { while (running) { int produced = Interlocked.Increment(ref i); "Prod will lock".Dump(); lock (queue) { "Prod locked".Dump(); queue.Enqueue(produced); if(produced > 30){ running = false; } ("Prod produced " + produced).Dump(); "Prod will pulse".Dump(); Monitor.Pulse(queue); "Prod pulsed, will unlock".Dump(); } "Prod unlocked".Dump(); } } private void ConsumerThreadProc() { while (running) { int toBeConsumed; "Cons will lock".Dump(); lock (queue) { if (queue.Count == 0) { "Cons locked, will start to wait".Dump(); Monitor.Wait(queue); "Cons done waiting".Dump(); } toBeConsumed = queue.Dequeue(); consumed = toBeConsumed; ("Cons Consumed " + toBeConsumed).Dump(); "Cons will unlock".Dump(); } "Cons unlocked".Dump(); } } }