/// <summary> /// This is called by the worker thread when it finishes it's current job. It adds the worker thread back into the /// queue of available threads. /// </summary> /// <param name="sender"> This should always be a reference to the GenericThread that has finished. </param> /// <param name="e"> Nothing interesting in here. </param> private void JobFinished(object sender, EventArgs e) { Debug.Assert(sender is GenericThread); GenericThread gt = (GenericThread)sender; // Add the thread back into the 'free' list. int busyListCount; lock (_threadBusyListLock) { bool c**k = _threadBusyList.Remove(gt); Debug.Assert(c**k == true); busyListCount = _threadBusyList.Count; // If we're ending the last thread, the threads are now idle. if (busyListCount == 0) { this.ThreadsAreIdle.Set(); } // Keep this outside of any lock. OnThreadBusyCountChangedEvent(busyListCount + 1, busyListCount); } // This is a ThreadSafe queue so we don't need to lock before Enqueueing. _threadAvailableList.Enqueue(gt); }
/// <summary> /// If the job queue is not empty and there is an available worker thread then the next job is sent to the worker thread. /// </summary> private void PokeTheQueue() { if (_bSuspendQueue == false) { int oldQueueSize, newQueueSize; lock (_jobQueue) { oldQueueSize = _jobQueue.Count; if (_jobQueue.Count > 0) { lock (_threadAvailableList) { // Use a 'while' rather than an 'if' because although this function is called each time a job is queued // and each time a worker thread becomes available and there therefore the worker threads should always // be saturated, if the queue is suspended then jobs aren't picked out of the queue when threads become available. while (_threadAvailableList.Count > 0 && _jobQueue.Count > 0) { GenericThread genericThread = _threadAvailableList.Dequeue(); lock (_threadBusyList) { _threadBusyList.Add(genericThread); } Job nextJob = _jobQueue.Dequeue().WrappedJob; //Debug.WriteLine("Starting Job named '"+nextJob.Name+"'. Queue Size: " + _jobQueue.Count); genericThread.StartJob(nextJob); } } } newQueueSize = _jobQueue.Count; } if (oldQueueSize != newQueueSize) // Keep this outside of the lock. { OnThreadManagerQueueSizeChangedEvent(_jobQueue.Count + 1, _jobQueue.Count); } } }