/// <summary> /// The procedure used to perform work on the array. /// </summary> /// <param name="data">The ID of the thread cast to an object.</param> private void ConsumerThreadProcedure(object data) { int myID = (int)data; try { while (true) { PrepBarrier.SignalAndWait(); //This second loop is necessary so that the worker thread keeps trying to //consume data if there is data left on the queue. The previous version //worked only because there were 8 threads and exactly 8 pieces of work to //be done each frame. If the grid was increased in size it would break because //not all of the work would be done each frame. This fixes that issue. while (true) { WorkOrder w = null; lock (queueLock) { if (WorkQueue.Count > 0) { //grab the work w = WorkQueue.Dequeue(); } else { break; } } Console.WriteLine("Thread: " + myID.ToString() + " has acquired its lock and will begin working"); if (w != null) { //Process the work order. for (int i = w.rowIndex; i < w.rowIndex + w.rowCount; ++i) { for (int j = 0; j < DIMENSIONY; ++j) { if (b1[i, j] == 1) { ProcessAlivePixel(i, j); } else { ProcessDeadPixel(i, j); } } } } } WorkBarrier.SignalAndWait(); ProcessBarrier.SignalAndWait(); } } catch (ThreadAbortException ex) { return; } }
/// <summary> /// The thread procedure that controls all worker threads. /// </summary> private void LockedThreadProcedure() { try { //Set up and start the worker threads. for (int i = 0; i < threadCount; ++i) { Thread t = new Thread(ConsumerThreadProcedure); t.Start(i); workerThreads.Add(t); } while (true) { while (running) { Console.WriteLine("Setting up the work orders"); //set up the work load. ClearArray(b2); Stopwatch clock = new Stopwatch(); clock.Start(); int numberChunks = DIMENSIONX / workChunkSize; for (int i = 0; i < numberChunks; ++i) { WorkOrder w = new WorkOrder(); w.rowCount = workChunkSize; w.rowIndex = i * workChunkSize; WorkQueue.Enqueue(w); } PrepBarrier.SignalAndWait(); Console.WriteLine("Waiting for workers to finish"); WorkBarrier.SignalAndWait(); Console.WriteLine("Processing data"); //Process the results from the worker threads. ++generation; LoadArrayIntoBitmap(b2); ClearArray(b1); for (int i = 0; i < DIMENSIONX; ++i) { for (int j = 0; j < DIMENSIONY; ++j) { b1[i, j] = b2[i, j]; } } UpdateGenerationLabel(generation); SetPictureBoxImage(img); UpdatePictureBox(); clock.Stop(); long elapsedtime = clock.ElapsedMilliseconds; if (elapsedtime < (long)threadSleepTime) { long delta = (long)threadSleepTime - elapsedtime; Thread.Sleep((int)delta); } ProcessBarrier.SignalAndWait(); } } } catch (ThreadAbortException ex) { //If this thread is aborted, we need to also stop all the worker threads. foreach (Thread t in workerThreads) { t.Abort(); t.Join(); } return; } }