(c) 2002 Visual Studio Magazine 
Fawcette Technical Publications

C#	Use the Producer/Consumer Idiom.
Listing 1	You can protect access to the shared buffer by using the producer/consumer idiom. This class shows the two key routines in the buffer. AddValues puts data in the buffer and signals the reader that it's available.  readValues pulls data out and tells writers that the buffer is free.

public void AddValues (ArrayList vals)
{
	lock (this) 
	{
		if (_dataReady)
			Monitor.Wait (this);
		_primeList.AddRange (vals);
		_dataReady = true;
		Monitor.Pulse (this);
	}
}

public object [] readValues ()
{
	lock (this)
	{
		if (!_dataReady)
			Monitor.Wait (this);
			object [] rVal = new object [_qSize];
		_primeList.CopyTo (rVal);
		_dataReady = false;
		_primeList.Clear ();
		Monitor.Pulse (this);
		return rVal;
	}
}


C#	Calculate Primes in a Separate Thread.
Listing 2	This class creates a thread to calculate all the prime numbers from 1 to 10,000,000. It stores the primes in a local store you can export for other purposes. It writes a set of primes periodically to the intermediate storage objects where readers can access it.

public class PrimeCalc
{
	private const int MAX_NUM = 10000000;
	private PrimeStorage _theStore;
	private ArrayList _primes = new ArrayList ();
	public PrimeCalc(PrimeStorage theStorage)
	{
		_theStore = theStorage;
	}

	public Thread CreateProducerThread ()
	{
		return new Thread 
			(new ThreadStart (this.calculate));
	}

	private void calculate ()
	{
		int lastIndex =0;
		for (int i=2; i < MAX_NUM; i++)
		{
			if (isPrime (i))
			{
				_primes.Add (i);
				if (_primes.Count % _theStore.qSize 
					== 0)
				{
					_theStore.AddValues 
						(_primes.GetRange (lastIndex, 
						_theStore.qSize));
					lastIndex += _theStore.qSize;
				}
			}
		}
		_theStore.AddValues (_primes.GetRange 
			(lastIndex,_primes.Count - lastIndex));
		_theStore.Done = true;
	}

	private bool isPrime (int val)
	{

		int maxTest = (int)Math.Ceiling 
			(Math.Sqrt((double)val));
		for (int i=0;i< _primes.Count; i++)
		{
			if (val % (int)_primes[i] == 0)
				return false;
			if ((int)_primes[i] > maxTest)
				return true;
		}
		// No factors found, its prime:
		return true;
	}

	public ArrayList SynchList 
	{
		get
		{
			return ArrayList.Synchronized 
				(_primes);
		}
	}

	public int Count
	{
		get
		{
			lock (this)
				return _primes.Count;
		}
	}
}

