A particularly common scenario (with a typical question being "How can I shut down a worker thread?" Here's a code skeleton which just needs the work for the worker thread to perform to be filled in (and any member it needs, of course).
using System;
using System.Threading;
/// <summary>
/// Skeleton for a worker thread. Another thread would typically set up
/// an instance with some work to do, and invoke the Run method (eg with
/// new Thread(new ThreadStart(job.Run)).Start())
/// </summary>
public class Worker
{
/// <summary>
/// Lock covering _stopping and stopped
/// </summary>
private readonly object _stopLock = new object();
/// <summary>
/// Whether or not the worker thread has been asked to stop.
/// </summary>
private bool _stopping = false;
/// <summary>
/// Whether or not the worker thread has _stopped.
/// </summary>
private bool _stopped = false;
/// <summary>
/// Returns whether the worker thread has been asked to stop.
/// This continues to return true even after the thread has stopped.
/// </summary>
public bool Stopping
{
get
{
lock (_stopLock)
{
return _stopping;
}
}
}
/// <summary>
/// Returns whether the worker thread has stopped.
/// </summary>
public bool Stopped
{
get
{
lock (_stopLock)
{
return _stopped;
}
}
}
/// <summary>
/// Tells the worker thread to stop, typically after completing its
/// current work item. (The thread is *not* guaranteed to have stopped
/// by the time this method returns.)
/// </summary>
public void Stop()
{
lock (_stopLock)
{
_stopping = true;
}
}
/// <summary>
/// Called by the worker thread to indicate when it has stopped.
/// </summary>
void SetStopped()
{
lock (_stopLock)
{
_stopped = true;
}
}
/// <summary>
/// Main work loop of the class.
/// </summary>
public void Run()
{
try
{
while (!Stopping)
{
// Insert work here. Make sure it doesn't tight loop!
// (If work is arriving periodically, use a queue and Monitor.Wait,
// changing the Stop method to pulse the monitor as well as setting
// _stopping.)
// Note that you may also wish to break out *within* the loop
// if work items can take a very long time but have points at which
// it makes sense to check whether or not you've been asked to stop.
// Do this with just:
// if (Stopping)
// {
// return;
// }
// The finally block will make sure that the _stopped flag is set.
}
}
finally
{
SetStopped();
}
}
}