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();
}
}