I implemented this Agent class for a project recently and was wondering if I could get some other eyes to look at it -- I'm currently the only developer where I work so I can't exactly ask someone here to do it.
I'm pretty sure it's correct, but then I'm too close to it.
public abstract class Agent<M> : IDisposable
{
private Thread thread;
private Queue<M> messageQueue;
private bool quit;
public Agent()
{
this.thread = new Thread(new ThreadStart(AgentThreadBody));
this.messageQueue = new Queue<M>();
this.quit = false;
this.thread.Start();
}
/// <summary>
/// Stops the message-handling thread.
///
/// Do not call this method from within the message-
/// handling method, or it will result in a deadlock
/// (because this method waits for the message-handling
/// thread to stop).
/// </summary>
public virtual void Dispose()
{
this.quit = true;
this.thread.Interrupt();
this.thread.Join();
this.thread = null;
// clear messageQueue before nulling?
// (would do this to dispose queued items)
this.messageQueue = null;
}
public void QueueMessage(M message)
{
lock (this.messageQueue)
{
this.messageQueue.Enqueue(message);
this.thread.Interrupt();
}
}
private void AgentThreadBody()
{
while (!this.quit)
{
M message = default(M);
bool messageAvailable = false;
lock (messageQueue)
{
if (messageQueue.Count > 0)
{
message = messageQueue.Dequeue();
messageAvailable = true;
}
}
try
{
if (!messageAvailable)
{
// if the Interrupt() method was
// called before we sleep or is
// called while we're sleeping,
// this will throw:
// ThreadInterruptedException
Thread.Sleep(Timeout.Infinite);
}
}
catch (ThreadInterruptedException)
{
// we have a new message to handle,
// so get it, or we've been told
// to quit.
continue;
}
ProcessMessage(message);
}
}
protected abstract void ProcessMessage(M message);
}
Also, are there any special considerations you can think of that should be made by a class inheriting from this base class? (I can't think of any.)
I could add start/stop methods, but at the moment they're not needed.
Btw, I have to use .NET 3.5.