using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace WaitOne { class Program { static void Main(string[] args) { Calculate calc = new Calculate(); Console.WriteLine("Result = {0}.", calc.Result(234).ToString()); Console.WriteLine("Result = {0}.", calc.Result(55).ToString()); } static void WorkMethod(object stateInfo) { Console.WriteLine("Work starting."); // Simulate time spent working. Thread.Sleep(new Random().Next(100, 2000)); // Signal that work is finished. Console.WriteLine("Work ending."); ((AutoResetEvent)stateInfo).Set(); } } class Calculate { double baseNumber, firstTerm, secondTerm, thirdTerm; AutoResetEvent[] autoEvents; ManualResetEvent manualEvent; // Generate random numbers to simulate the actual calculations. Random randomGenerator; public Calculate() { autoEvents = new AutoResetEvent[] { new AutoResetEvent(false), new AutoResetEvent(false), new AutoResetEvent(false) }; manualEvent = new ManualResetEvent(false); } void CalculateBase(object stateInfo) { baseNumber = randomGenerator.NextDouble(); Console.WriteLine("Base start"); // Signal that baseNumber is ready. manualEvent.Set(); Console.WriteLine("Base work"); } // The following CalculateX methods all perform the same // series of steps as commented in CalculateFirstTerm. void CalculateFirstTerm(object stateInfo) { // Perform a precalculation. double preCalc = randomGenerator.NextDouble(); Console.WriteLine("First start"); // Wait for baseNumber to be calculated. manualEvent.WaitOne(); Console.WriteLine("First work."); // Calculate the first term from preCalc and baseNumber. firstTerm = preCalc * baseNumber * randomGenerator.NextDouble(); // Signal that the calculation is finished. autoEvents[0].Set(); } void CalculateSecondTerm(object stateInfo) { double preCalc = randomGenerator.NextDouble(); Console.WriteLine("Second Start.."); manualEvent.WaitOne(); Console.WriteLine("Second Work.."); secondTerm = preCalc * baseNumber * randomGenerator.NextDouble(); autoEvents[1].Set(); } void CalculateThirdTerm(object stateInfo) { double preCalc = randomGenerator.NextDouble(); Console.WriteLine("Third Start.."); manualEvent.WaitOne(); Console.WriteLine("Third work.."); thirdTerm = preCalc * baseNumber * randomGenerator.NextDouble(); autoEvents[2].Set(); } public double Result(int seed) { randomGenerator = new Random(seed); // Simultaneously calculate the terms. ThreadPool.QueueUserWorkItem( new WaitCallback(CalculateBase)); ThreadPool.QueueUserWorkItem( new WaitCallback(CalculateFirstTerm)); ThreadPool.QueueUserWorkItem( new WaitCallback(CalculateSecondTerm)); ThreadPool.QueueUserWorkItem( new WaitCallback(CalculateThirdTerm)); // Wait for all of the terms to be calculated. WaitHandle.WaitAll(autoEvents); // Reset the wait handle for the next calculation. manualEvent.Reset(); return firstTerm + secondTerm + thirdTerm; } } }