133 lines
No EOL
2.9 KiB
C#
133 lines
No EOL
2.9 KiB
C#
using System;
|
|
using System.Threading;
|
|
|
|
namespace JD.Threading
|
|
{
|
|
/// <summary>
|
|
/// A thread that starts on demand.
|
|
/// </summary>
|
|
public abstract class WakeUpThreadBase
|
|
{
|
|
#region Variables
|
|
|
|
private State m_state = State.Stopped;
|
|
private readonly ManualResetEvent m_stoppedEvent = new ManualResetEvent(true);
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
/// <summary>
|
|
/// True if there is currenlty something to do.
|
|
/// </summary>
|
|
public bool IsRunning
|
|
{
|
|
get { return m_state.IsRunning; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
protected void Join()
|
|
{
|
|
m_stoppedEvent.WaitOne();
|
|
}
|
|
|
|
protected void WakeUp()
|
|
{
|
|
State oldState = DoAndSetState(DoNothing, State.Running);
|
|
|
|
if (!oldState.IsRunning)
|
|
{
|
|
m_stoppedEvent.Reset();
|
|
QueueUserWorkItem(Execute);
|
|
}
|
|
}
|
|
|
|
private void Execute(object dummy)
|
|
{
|
|
try
|
|
{
|
|
DoAndSetState(DoWork, State.Stopped);
|
|
}
|
|
finally
|
|
{
|
|
m_stoppedEvent.Set();
|
|
}
|
|
}
|
|
|
|
private State DoAndSetState(Action action, State newState)
|
|
{
|
|
State oldState;
|
|
do
|
|
{
|
|
oldState = m_state;
|
|
action();
|
|
}
|
|
while (!AssignNewState(oldState, newState));
|
|
|
|
return oldState;
|
|
}
|
|
|
|
private static void DoNothing()
|
|
{ }
|
|
|
|
private bool AssignNewState(State currentState, State newState)
|
|
{
|
|
return Interlocked.CompareExchange(ref m_state, newState, currentState) == currentState;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Abstract
|
|
|
|
protected abstract void DoWork();
|
|
|
|
/// <summary>
|
|
/// Pushes the job on the ThreadPool.
|
|
/// </summary>
|
|
protected virtual void QueueUserWorkItem(WaitCallback waitCallBack)
|
|
{
|
|
System.Threading.ThreadPool.QueueUserWorkItem(waitCallBack);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Nested
|
|
|
|
private class State
|
|
{
|
|
private readonly bool m_isRunning;
|
|
|
|
private State(bool isRunning)
|
|
{
|
|
m_isRunning = isRunning;
|
|
}
|
|
|
|
public bool IsRunning
|
|
{
|
|
get { return m_isRunning; }
|
|
}
|
|
|
|
public static State Running
|
|
{
|
|
get
|
|
{
|
|
// Need to return a new object since we dont want two requests to be considered equals.
|
|
return new State(true);
|
|
}
|
|
}
|
|
|
|
public static State Stopped
|
|
{
|
|
get
|
|
{
|
|
return new State(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |