Thread C# Tutorial

/*
Quote from 
C# and the .NET Framework
by Bob Powell 
*/
using System;
using System.Threading;
public class Factory {
  private int[]  Widgets = new int[100];
  private int    WidgetIndex = 0;
  private AutoResetEvent NewWidgetEvent = new AutoResetEvent( false );
  protected void Producer( ) {
    while( true ) {
      lock( this ) {
        if( WidgetIndex < 100 ) {
          Widgets[ WidgetIndex ] = 1;
          Console.WriteLine("Widget {0} Produced", WidgetIndex++ );
          NewWidgetEvent.Set( );
        }
      }
      Thread.Sleep( (new Random()).Next( 5 ) * 1000 );
    }
  }
  protected void Consumer( ) {
    while( true ) {
      NewWidgetEvent.WaitOne( );
      int iWidgetIndex = 0;
      lock( this ) {
        iWidgetIndex = --this.WidgetIndex;
        Console.WriteLine("Consuming widget {0}", iWidgetIndex );  
        Widgets[ iWidgetIndex-- ] = 0;
      }
    }
  }
  public void Run( ) {
    for( int i = 0; i < 3; i++ ) {
      Thread producer = new Thread( new ThreadStart( Producer ) );
      producer.Start( );
    }
    for( int i = 0; i < 3; i++ ) {
      Thread consumer = new Thread( new ThreadStart( Consumer ) );
      consumer.Start( );
    }
  }
  public static void Main( ) {
    Factory factory = new Factory( );
    factory.Run( );
  }
}
Widget 0 Produced
Widget 1 Produced
Widget 2 Produced
Consuming widget 2
Widget 2 Produced
Consuming widget 2
Widget 2 Produced
Widget 3 Produced
Consuming widget 3
Consuming widget 2
Widget 2 Produced
Consuming widget 2
Widget 2 Produced
Widget 3 Produced
Consuming widget 3
Consuming widget 2
Widget 2 Produced
Consuming widget 2
^CTerminate batch job (Y/N)? n