Csharp/C Sharp/Thread/Thread Sync

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

Another way to use lock to synchronize access to an object

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

// Another way to use lock to synchronize access to an object.

using System; using System.Threading;

class SumArray {

 int sum;  
 
 public int sumIt(int[] nums) {  
   sum = 0; // reset sum  
 
   for(int i=0; i < nums.Length; i++) {  
     sum += nums[i];  
     Console.WriteLine("Running total for " +  
            Thread.CurrentThread.Name +  
            " is " + sum);  
     Thread.Sleep(10); // allow task-switch  
   }  
   return sum; 
 }  

}

class MyThread {

 public Thread thrd;  
 int[] a;  
 int answer; 

 /* Create one SumArray object for all 
    instances of MyThread. */ 
 static SumArray sa = new SumArray();  

 // Construct a new thread.  
 public MyThread(string name, int[] nums) {  
   a = nums;  
   thrd = new Thread(new ThreadStart(this.run)); 
   thrd.Name = name; 
   thrd.Start(); // start the thread  
 }  
 
 // Begin execution of new thread.  
 void run() {  
   Console.WriteLine(thrd.Name + " starting.");  
 
   // Lock calls to sumIt().  
   lock(sa) answer = sa.sumIt(a); 

   Console.WriteLine("Sum for " + thrd.Name +  
                      " is " + answer);  
 
   Console.WriteLine(thrd.Name + " terminating.");  
 }  

}

public class Sync2 {

 public static void Main() {  
   int[] a = {1, 2, 3, 4, 5};  
 
   MyThread mt1 = new MyThread("Child #1", a);  
   MyThread mt2 = new MyThread("Child #2", a);  
 
   mt1.thrd.Join();  
   mt2.thrd.Join();  
 }  

}


      </source>


A synchronized shared buffer implementation

<source lang="csharp">

using System; using System.Threading; public class SynchronizedBuffer {

  private int buffer = -1; 
  private int occupiedBufferCount = 0;  
  public int Buffer
  {      
     get
     { 
        Monitor.Enter( this );
        if ( occupiedBufferCount == 0 )
        {
           Console.WriteLine(Thread.CurrentThread.Name + " tries to read." );
           DisplayState( "Buffer empty. " +Thread.CurrentThread.Name + " waits." );
           Monitor.Wait( this );
        } 
        --occupiedBufferCount;    
                             
        DisplayState( Thread.CurrentThread.Name + " reads " + buffer );
        Monitor.Pulse( this );
        int bufferCopy = buffer;
        Monitor.Exit( this );
        return bufferCopy;
     }
     set
     {
        Monitor.Enter( this );
        if ( occupiedBufferCount == 1 )
        {
           Console.WriteLine(Thread.CurrentThread.Name + " tries to write." );
           DisplayState( "Buffer full. " + Thread.CurrentThread.Name + " waits." );
           Monitor.Wait( this );
        }
        buffer = value;
        ++occupiedBufferCount;
        DisplayState( Thread.CurrentThread.Name + " writes " + buffer );
        Monitor.Pulse( this );
        Monitor.Exit( this );
     } 
  }
  public void DisplayState( string operation )
  {
     Console.WriteLine( "{0,-35}{1,-9}{2}\n",operation, buffer, occupiedBufferCount );
  }
  static void Main( string[] args )
  {
     SynchronizedBuffer shared = new SynchronizedBuffer();
     Random random = new Random();
     Console.WriteLine( "{0,-35}{1,-9}{2}\n","Operation", "Buffer", "Occupied Count" );
     shared.DisplayState( "Initial state" );
     Producer producer = new Producer( shared, random );
     Consumer consumer = new Consumer( shared, random );
     Thread producerThread = new Thread( new ThreadStart( producer.Produce ) );
     producerThread.Name = "Producer";
     Thread consumerThread = new Thread( new ThreadStart( consumer.Consume ) );
     consumerThread.Name = "Consumer";
     producerThread.Start();
     consumerThread.Start();
  }

} public class Consumer {

  private SynchronizedBuffer sharedLocation;
  private Random randomSleepTime;
  public Consumer( SynchronizedBuffer shared, Random random )
  {
     sharedLocation = shared;
     randomSleepTime = random;
  }
  public void Consume()
  {
     int sum = 0;
     for ( int count = 1; count <= 10; count++ )
     {
        Thread.Sleep( randomSleepTime.Next( 1, 1001 ) );
        sum += sharedLocation.Buffer;
     }
     Console.WriteLine("{0} read values totaling: {1}.\nTerminating {0}.",Thread.CurrentThread.Name, sum );
  }

} public class Producer {

  private SynchronizedBuffer sharedLocation;
  private Random randomSleepTime;
  public Producer( SynchronizedBuffer shared, Random random )
  {
     sharedLocation = shared;
     randomSleepTime = random;
  }
  public void Produce()
  {
     for ( int count = 1; count <= 10; count++ ) 
     {
        Thread.Sleep( randomSleepTime.Next( 1, 1001 ) );
        sharedLocation.Buffer = count; 
     }
     Console.WriteLine( "{0} done producing.\nTerminating {0}.",Thread.CurrentThread.Name );
  }

}


      </source>


Asynchronous Calls:A Simple Example 1

<source lang="csharp">

/* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3

  • /

// 29 - Threading and Asynchronous Operations\Asynchronous Calls\A Simple Example // copyright 2000 Eric Gunnerson using System;

public class AsynchronousCallsASimpleExample {

   public static void Main()
   {
       AsyncCaller ac = new AsyncCaller();
       ac.CallWriteLine("Hello");
   }

} public class AsyncCaller {

   // Declare a delegate that will match Console.WriteLine("string");
   delegate void FuncToCall(string s);
   
   public void CallWriteLine(string s)
   {
       // delegate points to function to call
       // start the async call
       // wait for completion
       FuncToCall func = new FuncToCall(Console.WriteLine);
       IAsyncResult iar = func.BeginInvoke(s, null, null);
       func.EndInvoke(iar);
   }

}

      </source>


Asynchronous Calls:A Simple Example 2

<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3

  • /

// 29 - Threading and Asynchronous Operations\Asynchronous Calls\A Simple Example // copyright 2000 Eric Gunnerson using System; public class AsynchronousCallsASimpleExample2 {

   public static void Main()
   {
       AsyncCaller ac = new AsyncCaller();
       
       ac.CallWriteLineWithCallback("Hello There");
       
       System.Threading.Thread.Sleep(1000);
   }

} public class AsyncCaller {

   // Declare a delegate that will match Console.WriteLine("string");
   delegate void FuncToCall(string s);
   
   public void WriteLineCallback(IAsyncResult iar)
   {
       Console.WriteLine("In WriteLineCallback");
       FuncToCall func = (FuncToCall) iar.AsyncState;
       func.EndInvoke(iar);
   }
   
   public void CallWriteLineWithCallback(string s)
   {
       FuncToCall func = new FuncToCall(Console.WriteLine);
       func.BeginInvoke(s, 
       new AsyncCallback(WriteLineCallback), 
       func); // shows up as iar.AsyncState in callback
   }

}

      </source>


Asynchronous Calls:Return Values

<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3

  • /

// 29 - Threading and Asynchronous Operations\Asynchronous Calls\Return Values // copyright 2000 Eric Gunnerson using System; using System.Threading;

public class AsynchronousCallsReturnValues {

   public static void Main()
   {
       AsyncCaller ac = new AsyncCaller();
       
       ac.CallMathCallback(new AsyncCaller.MathFunctionToCall(Math.Sin), 0.0, 1.0, 0.2);
       Thread.Sleep(2000);
   }

} public class AsyncCaller {

   public delegate double MathFunctionToCall(double arg);
   
   public void MathCallback(IAsyncResult iar)
   {
       MathFunctionToCall mc = (MathFunctionToCall) iar.AsyncState;
       double result = mc.EndInvoke(iar);
       Console.WriteLine("Function value = {0}", result);
   }
   public void CallMathCallback(MathFunctionToCall mathFunc,
   double start,
   double end,
   double increment)
   {
       AsyncCallback cb = new AsyncCallback(MathCallback);
       
       while (start < end)
       {    
           Console.WriteLine("BeginInvoke: {0}", start);
           mathFunc.BeginInvoke(start, cb, mathFunc);
           start += increment;
       }
   }

}


      </source>


Asynchronous Calls:Waiting for Completion

<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3

  • /

// 29 - Threading and Asynchronous Operations\Asynchronous Calls\Waiting for Completion // copyright 2000 Eric Gunnerson using System; using System.Threading;

public class AsynchronousCallsWaitingforCompletion1 {

   public static double DoCalculation(double value)
   {
       Console.WriteLine("DoCalculation: {0}", value);
       Thread.Sleep(250);
       return(Math.Cos(value));
   }
   
   public static void Main()
   {
       AsyncCaller ac = new AsyncCaller();
       
       ac.CallMathCallback(new AsyncCaller.MathFunctionToCall(DoCalculation));
       //Thread.Sleep(500);        // no longer needed
   }

} public class AsyncCaller {

   public delegate double MathFunctionToCall(double arg);
   
   public void MathCallback(IAsyncResult iar)
   {
       MathFunctionToCall mc = (MathFunctionToCall) iar.AsyncState;
       double result = mc.EndInvoke(iar);
       Console.WriteLine("Function value = {0}", result);
   }
   
   WaitHandle DoInvoke(MathFunctionToCall mathFunc, double value)
   {
       AsyncCallback cb = new AsyncCallback(MathCallback);
       
       IAsyncResult asyncResult = 
       mathFunc.BeginInvoke(value, cb, mathFunc);
       return(asyncResult.AsyncWaitHandle);
   }
   
   public void CallMathCallback(MathFunctionToCall mathFunc)
   {
       WaitHandle[] waitArray = new WaitHandle[4];
       
       Console.WriteLine("Begin Invoke");
       waitArray[0] = DoInvoke(mathFunc, 0.1);
       waitArray[1] = DoInvoke(mathFunc, 0.5);
       waitArray[2] = DoInvoke(mathFunc, 1.0);
       waitArray[3] = DoInvoke(mathFunc, 3.14159);
       Console.WriteLine("Begin Invoke Done");
       
       Console.WriteLine("Waiting for completion");
       WaitHandle.WaitAll(waitArray, 10000, false);
       Console.WriteLine("Completion achieved");
   }

}


      </source>


Asynchronous Calls:Waiting for Completion 2

<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3

  • /

// 29 - Threading and Asynchronous Operations\Asynchronous Calls\Waiting for Completion // copyright 2000 Eric Gunnerson using System; using System.Threading;

public class AsynchronousCallsWaitingforCompletion2 {

   public static double DoCalculation(double value)
   {
       Console.WriteLine("DoCalculation: {0}", value);
       Thread.Sleep(250);
       return(Math.Cos(value));
   }
   
   public static void Main()
   {
       AsyncCaller ac = new AsyncCaller();
       
       ac.CallMathCallback(new AsyncCaller.MathFunctionToCall(DoCalculation));
   }

} public class AsyncCallTracker {

   Delegate function;
   AutoResetEvent doneEvent;
   
   public AutoResetEvent DoneEvent
   {
       get
       {
           return(doneEvent);
       }
   }
   
   public Delegate Function
   {
       get
       {
           return(function);
       }
   }
   
   public AsyncCallTracker(Delegate function)
   {
       this.function = function;
       doneEvent = new AutoResetEvent(false);
   }

} public class AsyncCaller {

   public delegate double MathFunctionToCall(double arg);
   
   public void MathCallback(IAsyncResult iar)
   {
       AsyncCallTracker callTracker = (AsyncCallTracker) iar.AsyncState;
       MathFunctionToCall func = (MathFunctionToCall) callTracker.Function;
       double result = func.EndInvoke(iar);
       Console.WriteLine("Function value = {0}", result);
       callTracker.DoneEvent.Set();
   }
   
   WaitHandle DoInvoke(MathFunctionToCall mathFunc, double value)
   {
       AsyncCallTracker callTracker = new AsyncCallTracker(mathFunc);
       
       AsyncCallback cb = new AsyncCallback(MathCallback);
       IAsyncResult asyncResult = mathFunc.BeginInvoke(value, cb, callTracker);
       return(callTracker.DoneEvent);
   }
   
   public void CallMathCallback(MathFunctionToCall mathFunc)
   {
       WaitHandle[] waitArray = new WaitHandle[4];
       
       Console.WriteLine("Begin Invoke");
       waitArray[0] = DoInvoke(mathFunc, 0.1);
       waitArray[1] = DoInvoke(mathFunc, 0.5);
       waitArray[2] = DoInvoke(mathFunc, 1.0);
       waitArray[3] = DoInvoke(mathFunc, 3.14159);
       Console.WriteLine("Begin Invoke Done");
       
       Console.WriteLine("Waiting for completion");
       WaitHandle.WaitAll(waitArray, 10000, false);
       Console.WriteLine("Completion achieved");
   }

}


      </source>


Data Protection and Synchronization:A Slightly Broken Example

<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3

  • /

// 29 - Threading and Asynchronous Operations\Data Protection and Synchronization\A Slightly Broken Example // copyright 2000 Eric Gunnerson using System; using System.Threading; class Val {

   int number = 1;
   
   public void Bump()
   {
       int temp = number;
       number = temp + 2;
   }
   
   public override string ToString()
   {
       return(number.ToString());
   }
   
   public void DoBump()
   {
       for (int i = 0; i < 5; i++)
       {
           Bump();
           Console.WriteLine("number = {0}", number);
       }
   }

} public class DataProtectionandSynchronizationASlightlyBrokenExample {

   public static void Main()
   {
       Val v = new Val();
       
       for (int threadNum = 0; threadNum < 5; threadNum++)
       {
           Thread thread = new Thread(new ThreadStart(v.DoBump));
           thread.Start();
       }
   }

}

      </source>


illustrates the use of the Mutex object

<source lang="csharp"> /* Mastering Visual C# .NET by Jason Price, Mike Gunderloy Publisher: Sybex; ISBN: 0782129110

  • /

/*

 Example14_11.cs illustrates the use of the Mutex object
  • /

using System; using System.Threading; public class Example14_11 {

 // a shared counter
 private static int Runs = 0;
 // a mutex
 static Mutex mtx;
 // the CountUp method increments the shared counter
 public static void CountUp() 
 {
   while (Runs < 10)
   {
     // acquire the mutex
     mtx.WaitOne();
     int Temp = Runs;
     Temp++;
     Console.WriteLine(Thread.CurrentThread.Name + " " + Temp);
     Thread.Sleep(1000);
     Runs = Temp;
     // release the mutex
     mtx.ReleaseMutex();
   } 
 }
 public static void Main() 
 {
   // create the mutex
   mtx = new Mutex(false, "RunsMutex");
   // create and launch two threads
   Thread t2 = new Thread(new ThreadStart(CountUp));
   t2.Name = "t2";
   Thread t3 = new Thread(new ThreadStart(CountUp));
   t3.Name = "t3";
   t2.Start();
   t3.Start();
 }

}


      </source>


My Main Class Async Call back

<source lang="csharp"> /*

* C# Programmers Pocket Consultant
* Author: Gregory S. MacBeth
* Email: gmacbeth@comporium.net
* Create Date: June 27, 2003
* Last Modified Date:
* Version: 1
*/

using System; using System.Threading; using System.Runtime.Remoting.Messaging; namespace Client.Chapter_15___Threading {

 public class MyMainClassAsyncCallback
 {
   delegate int MyDelegate(string s, ref int a, ref int b);
   static void Main(string[] args)
   {
     MyDelegate X = new MyDelegate(DoSomething);
     int a = 0;
     int b = 0;
     //Making Async Call that calls a callback when finished
     AsyncCallback cb = new AsyncCallback(DoSomething2);
     IAsyncResult ar = X.BeginInvoke("Hello", ref a, ref b, cb, null);
     Console.ReadLine();
   }
   //My Async Method
   static int DoSomething(string s, ref int a, ref int b)
   {
     a = 10;
     b = 100;
     Console.WriteLine("Fired! DoSomething1");
     return 0;
   }
   //Mycallback method when finished running DoSomehting
   static void DoSomething2(IAsyncResult ar)
   {
     int a = 0;
     int b = 0;
     Console.WriteLine("Fired! DoSomething2");
     //Get the delegate
     MyDelegate X = (MyDelegate)((AsyncResult)ar).AsyncDelegate;
     //get results
     X.EndInvoke(ref a, ref b, ar);
     Console.WriteLine(a);
     Console.WriteLine(b);
   }
 }

}

      </source>


MyMain Class Async Wait Timeout

<source lang="csharp"> /*

* C# Programmers Pocket Consultant
* Author: Gregory S. MacBeth
* Email: gmacbeth@comporium.net
* Create Date: June 27, 2003
* Last Modified Date:
* Version: 1
*/

using System; using System.Runtime.Remoting.Messaging; namespace Client.Chapter_15___Threading {

 public class MyMainClassAsyncWaitTimeout
 {
   delegate int MyDelegate(string s, ref int a, ref int b);
   static void Main(string[] args)
   {
     MyDelegate X = new MyDelegate(DoSomething);
     int a = 0;
     int b = 0;
     IAsyncResult ar = X.BeginInvoke("Hello", ref a, ref b, null, null);
     ar.AsyncWaitHandle.WaitOne(10000, false);
     if (ar.IsCompleted)
     {
       int c = 0;
       int d = 0;
       //get results
       X.EndInvoke(ref c, ref d, ar);
       Console.WriteLine(c);
       Console.WriteLine(d);
     }
   }
   //My Async Method
   static int DoSomething(string s, ref int a, ref int b)
   {
     a = 10;
     b = 100;
     Console.WriteLine("Fired! DoSomething1");
     return 0;
   }
 }

}

      </source>


Threading and Asynchronous Operations:Access Reordering and Volatile

<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3

  • /

// 29 - Threading and Asynchronous Operations\Access Reordering and Volatile // copyright 2000 Eric Gunnerson using System; using System.Threading; class Problem {

   int x;
   int y;
   int curx;
   int cury;
   
   public Problem()
   {
       x = 0;
       y = 0;
   }
   
   public void Process1()
   {
       x = 1;
       cury = y;
   }
   
   public void Process2()
   {
       y = 1;
       curx = x;
   }
   
   public void TestCurrent()
   {
       Console.WriteLine("curx, cury: {0} {1}", curx, cury);
   }

} public class AccessReorderingandVolatile {

   public static void Main()
   {
       Problem p = new Problem();
       
       Thread t1 = new Thread(new ThreadStart(p.Process1));        
       Thread t2 = new Thread(new ThreadStart(p.Process2));        
       t1.Start();
       t2.Start();
       
       t1.Join();
       t2.Join();
       
       p.TestCurrent();
   }

}

      </source>


Threading Class Mutex

<source lang="csharp"> /*

* C# Programmers Pocket Consultant
* Author: Gregory S. MacBeth
* Email: gmacbeth@comporium.net
* Create Date: June 27, 2003
* Last Modified Date:
* Version: 1
*/

using System; using System.Collections; using System.Threading; namespace Client.Chapter_15___Threading {

 public class ThreadingClassMutex
 {
   public static Thread ThreadOne = new Thread(new ThreadStart(MutexExample));
   public static ArrayList MyList = new ArrayList();
   private static Mutex MyMutex = new Mutex(false, "MyMutex");
   public ThreadingClassMutex()
   {
     MyList.Add("Test1");
     MyList.Add("Test2");
   }
   static void Main(string[] args)
   {
     ThreadOne.Start();
   }
   protected static void MutexExample()
   {
     MyMutex.WaitOne();
     MyList.Add("Test3");
     MyMutex.ReleaseMutex();
   }
 }

}

      </source>


Use lock to synchronize access to an object

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

// Use lock to synchronize access to an object.

using System; using System.Threading;

class SumArray {

 int sum;  
 
 public int sumIt(int[] nums) {  
   lock(this) { // lock the entire method 
     sum = 0; // reset sum  
   
     for(int i=0; i < nums.Length; i++) {  
       sum += nums[i];  
       Console.WriteLine("Running total for " +  
              Thread.CurrentThread.Name +  
              " is " + sum);  
       Thread.Sleep(10); // allow task-switch  
     }  
     return sum; 
   } 
 }  

}

class MyThread {

 public Thread thrd;  
 int[] a;  
 int answer; 

 /* Create one SumArray object for all 
    instances of MyThread. */ 
 static SumArray sa = new SumArray();  

 // Construct a new thread.  
 public MyThread(string name, int[] nums) {  
   a = nums;  
   thrd = new Thread(new ThreadStart(this.run)); 
   thrd.Name = name; 
   thrd.Start(); // start the thread  
 }  
 
 // Begin execution of new thread.  
 void run() {  
   Console.WriteLine(thrd.Name + " starting.");  
 
   answer = sa.sumIt(a);           

   Console.WriteLine("Sum for " + thrd.Name +  
                      " is " + answer);  
 
   Console.WriteLine(thrd.Name + " terminating.");  
 }  

}

public class Sync {

 public static void Main() {  
   int[] a = {1, 2, 3, 4, 5};  
 
   MyThread mt1 = new MyThread("Child #1", a);  
   MyThread mt2 = new MyThread("Child #2", a);  
 
   mt1.thrd.Join();  
   mt2.thrd.Join();  
 }  

}


      </source>


Use MethodImplAttribute to synchronize a method

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

// Use MethodImplAttribute to synchronize a method.

using System; using System.Threading; using System.Runtime.rupilerServices;

class TickTock {

 /* The following attribute synchronizes the entire 
    tick() method. */ 
 [MethodImplAttribute(MethodImplOptions.Synchronized)] 
 public void tick(bool running) { 
   if(!running) { // stop the clock 
     Monitor.Pulse(this); // notify any waiting threads 
     return; 
   } 

   Console.Write("Tick "); 
   Monitor.Pulse(this); // let tock() run 
  
   Monitor.Wait(this); // wait for tock() to complete 
 } 


 /* The following attribute synchronizes the entire 
    tock() method. */ 
 [MethodImplAttribute(MethodImplOptions.Synchronized)] 
 public void tock(bool running) { 
   if(!running) { // stop the clock 
     Monitor.Pulse(this); // notify any waiting threads 
     return; 
   } 

   Console.WriteLine("Tock"); 
   Monitor.Pulse(this); // let tick() run 

   Monitor.Wait(this); // wait for tick to complete 
 } 

}

class MyThread {

 public Thread thrd; 
 TickTock ttOb; 

 // Construct a new thread. 
 public MyThread(string name, TickTock tt) { 
   thrd = new Thread(new ThreadStart(this.run)); 
   ttOb = tt; 
   thrd.Name = name; 
   thrd.Start();  
 } 

 // Begin execution of new thread. 
 void run() { 
   if(thrd.Name == "Tick") { 
     for(int i=0; i<5; i++) ttOb.tick(true); 
     ttOb.tick(false); 
   } 
   else { 
     for(int i=0; i<5; i++) ttOb.tock(true); 
     ttOb.tock(false); 
   } 
 } 

}

public class TickingClock1 {

 public static void Main() { 
   TickTock tt = new TickTock(); 
   MyThread mt1 = new MyThread("Tick", tt); 
   MyThread mt2 = new MyThread("Tock", tt); 

   mt1.thrd.Join(); 
   mt2.thrd.Join(); 
   Console.WriteLine("Clock Stopped"); 
 } 

}


      </source>


Use Wait() and Pulse() to create a ticking clock

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

// Use Wait() and Pulse() to create a ticking clock.

using System; using System.Threading;

class TickTock {

 public void tick(bool running) { 
   lock(this) { 
     if(!running) { // stop the clock 
       Monitor.Pulse(this); // notify any waiting threads 
       return; 
     } 

     Console.Write("Tick "); 
     Monitor.Pulse(this); // let tock() run 
  
     Monitor.Wait(this); // wait for tock() to complete 
   } 
 } 

 public void tock(bool running) { 
   lock(this) { 
     if(!running) { // stop the clock 
       Monitor.Pulse(this); // notify any waiting threads 
       return; 
     } 

     Console.WriteLine("Tock"); 
     Monitor.Pulse(this); // let tick() run 

     Monitor.Wait(this); // wait for tick to complete 
   } 
 } 

}

class MyThread {

 public Thread thrd; 
 TickTock ttOb; 

 // Construct a new thread. 
 public MyThread(string name, TickTock tt) { 
   thrd = new Thread(new ThreadStart(this.run)); 
   ttOb = tt; 
   thrd.Name = name; 
   thrd.Start();  
 } 

 // Begin execution of new thread. 
 void run() { 
   if(thrd.Name == "Tick") { 
     for(int i=0; i<5; i++) ttOb.tick(true); 
     ttOb.tick(false); 
   } 
   else { 
     for(int i=0; i<5; i++) ttOb.tock(true); 
     ttOb.tock(false); 
   } 
 } 

}

public class TickingClock {

 public static void Main() { 
   TickTock tt = new TickTock(); 
   MyThread mt1 = new MyThread("Tick", tt); 
   MyThread mt2 = new MyThread("Tock", tt); 

   mt1.thrd.Join(); 
   mt2.thrd.Join(); 
   Console.WriteLine("Clock Stopped"); 
 } 

}


      </source>