The working logic
-Start one action inspecific offset
-Stop the actionafter the specific duration
-Re-start the actionafter specific cycle time
How to do
-Using the concept ofstate machine
-Using delegate tomake it Object Oriented
Key point
-State define
class TimeState
{
public static readonly TimeState Idle =new TimeState("Idle");
public static readonly TimeStateInDuration = new TimeState("InDuration");
public static readonly TimeStateWaitingForCycleStart = new TimeState("WaitingForCycleStart");
public static readonly TimeStateInOffSet = new TimeState("InOffSet");
string _status = string.Empty;
public TimeState(string state)
{
_status = state;
}
public override string ToString()
{
return _status;
}
}
-Transition statefrom one to another
-Monitor statechanges
-Action to perform
classTimeSessionMember
{
public Action Start;
public Action Stop;
}
Implementation
-Using a timer to settimer interval and tracking the state changes
-Using Reset to resetthe timer interval to transit to other state
-To be added: threadsafe
class stateMachine
{
TimerItem _item;
TimeState _timeState = TimeState.Idle;
TimeSessionConfig _timeSessionConf ;
List<TimeSessionMember>_listAction=new List<TimeSessionMember>();
public void AddAction(TimeSessionMembertimeSessionMember)
{
_listAction.Add(timeSessionMember);
}
private void startAction()
{
foreach (var item in _listAction)
{
item.Start();
}
}
private void stopAction()
{
foreach (var item in _listAction)
{
item.Stop();
}
}
public stateMachine(TimeSessionConfigconfig)
{
_timeSessionConf = config;
_item = new TimerItem(newTimerWheel(), TimeSpan.FromSeconds(1));
_item.Expired += _item_Expired;
}
void _item_Expired(object sender,EventArgs e)
{
TransitionState();
}
private void TransitionState()
{
if (_timeState == TimeState.Idle)
{
_timeState =TimeState.InOffSet;
if (_timeSessionConf.OffSet> 0)
{
_item.Reset(TimeSpan.FromSeconds(_timeSessionConf.OffSet));
return;
}
}
if (_timeState ==TimeState.InOffSet)
{
log(_timeState,TimeState.InDuration);
_timeState =TimeState.InDuration;
if (_timeSessionConf.InDuration> 0)
{
//start action now
startAction();
_item.Reset(TimeSpan.FromSeconds(_timeSessionConf.InDuration));
}
}
else if (_timeState ==TimeState.InDuration)
{
log(_timeState,TimeState.WaitingForCycleStart);
_timeState =TimeState.WaitingForCycleStart;
int shoulder =_timeSessionConf.Cycle - _timeSessionConf.OffSet - _timeSessionConf.InDuration;
stopAction();
//stop action now
if (shoulder > 0)
{
_item.Reset(TimeSpan.FromSeconds(shoulder));
}
else
{
//start it righ away
TransitionState();
}
}
else if (_timeState ==TimeState.WaitingForCycleStart)
{
log(_timeState,TimeState.Idle);
_timeState = TimeState.Idle;
TransitionState();
}
}
//start the state machine
public void Start()
{
TransitionState();
}
public void Stop()
{
_item.Stop();
}
private void log(TimeStatepre,TimeState status)
{
Console.WriteLine("Statemachine status transit from {0} to {1}", pre.ToString(),status.ToString());
}
}
static void Main(string[] args)
{
stateMachine stateMachine = newstateMachine(new TimeSessionConfig(1,9,10));
Action start=()=>{Console.WriteLine("action started.");};
Action stop=()=>{Console.WriteLine("action stoped.");};
TimeSessionMembertimeSessionMember= new TimeSessionMember();
timeSessionMember.Stop=stop;
timeSessionMember.Start=start;
stateMachine.AddAction(timeSessionMember);
stateMachine.Start();
Console.ReadLine();
}