using System; using System.Threading; using Chernobyl.DesignPatterns.Pool; using Chernobyl.Utility; using System.Diagnostics; namespace Chernobyl.Threading.Workers { /// /// Worker is both a helper class for implementing new IWorkers and /// a default worker implementation. /// public class Worker : IWorker { /// /// Constructor /// /// The name of this worker. /// The pool to pull jobs off of to /// work on. public Worker(string name, IPool jobPool) { WorkersThread = new Thread(Work); IsWorking = false; Name = name; } /// /// Tells the worker to begin working on the jobs assigned /// to him. /// virtual public void Start() { ThreadingPlugin.Trace.TraceEvent(TraceEventType.Start, 0, "The Worker \"" + this.Name + "\" is starting." + this.Name); lock (_isWorkingLocker) { if (IsWorking == true) return; IsWorking = true; } // begin executing WorkersThread.Start(); } /// /// Tells the worker to stop working on his jobs. /// virtual public void Stop() { ThreadingPlugin.Trace.TraceEvent(TraceEventType.Start, 0, "The Worker \"" + this.Name + "\" is stopping." + this.Name); lock (_isWorkingLocker) { if (IsWorking == false) return; IsWorking = false; } } /// /// True if this worker is working, i.e. was called /// and hasn't been called yet. /// public bool IsWorking { get; protected set; } /// /// Gets and sets the name of this worker. /// public string Name { get; set; } /// /// When this worker starts his workday this event is invoked. /// public event EventHandler OnWorkStart; /// /// When this worker ends his workday this event is invoked. /// public event EventHandler OnWorkEnd; /// /// The actual method that runs on the workers thread. /// Goes through the workers list of jobs and does them. /// virtual public void Work() { // check if someone is asking us to stop working while (IsWorking == true) { // inform listeners that work is starting if (OnWorkStart != null) OnWorkStart(this, EventArgs.Empty); Job job; lock (_jobPool) { JobPool.Take(out job); } // check if someone is asking us to stop working if (IsWorking == false) break; // otherwise do the next job job.DoJob(); // inform listeners that work has finished if (OnWorkEnd != null) OnWorkEnd(this, EventArgs.Empty); } } /// /// Gets/sets the thread that this worker runs his jobs on. /// public Thread WorkersThread { get; protected set; } /// /// The pool that the worker will pull jobs off /// of to work on. The worker is responsible for /// pulling getting jobs from the pool, working on /// those jobs, and then giving those jobs back. /// public IPool JobPool { get { return _jobPool; } set { lock (_jobPool) _jobPool = value; } } /// /// The backing field for . /// IPool _jobPool; /// /// An object that can be locked when access to is needed. /// readonly object _isWorkingLocker = new object(); } }