DeviceTimer
public class DeviceTimer { private enum DeviceTimerState { TM_ST_IDLE, TM_ST_BUSY, TM_ST_TIMEOUT } private DeviceTimerState _state; private long _startTime; private long _timeOut; private double _freq; private double _duration; [DllImport("Kernel32.dll")] private static extern bool QueryPerformanceCounter(out long lpPerformanceCount); [DllImport("Kernel32.dll")] private static extern bool QueryPerformanceFrequency(out long lpFrequency); public DeviceTimer() { if (!QueryPerformanceFrequency(out var lpFrequency)) { throw new Exception("本计算机不支持高性能计数器"); } _freq = (double)lpFrequency / 1000.0; SetState(DeviceTimerState.TM_ST_IDLE); QueryPerformanceCounter(out _startTime); _timeOut = _startTime; _duration = 0.0; } private void SetState(DeviceTimerState state) { _state = state; } private DeviceTimerState GetState() { return _state; } public double GetElapseTime() { QueryPerformanceCounter(out var lpPerformanceCount); return (double)(lpPerformanceCount - _startTime) / _freq; } public double GetTotalTime() { return _duration; } public void Stop() { SetState(DeviceTimerState.TM_ST_IDLE); QueryPerformanceCounter(out _startTime); _timeOut = _startTime; _duration = 0.0; } public void Start(double delay_ms) { QueryPerformanceCounter(out _startTime); _timeOut = Convert.ToInt64((double)_startTime + delay_ms * _freq); SetState(DeviceTimerState.TM_ST_BUSY); _duration = delay_ms; } public void Restart(double delay_ms) { _timeOut = Convert.ToInt64((double)_startTime + delay_ms * _freq); SetState(DeviceTimerState.TM_ST_BUSY); _duration = delay_ms; } public bool IsTimeout() { _ = _state; QueryPerformanceCounter(out var lpPerformanceCount); if (_state == DeviceTimerState.TM_ST_BUSY && lpPerformanceCount >= _timeOut) { SetState(DeviceTimerState.TM_ST_TIMEOUT); return true; } if (_state == DeviceTimerState.TM_ST_TIMEOUT) { return true; } return false; } public bool IsIdle() { return _state == DeviceTimerState.TM_ST_IDLE; } } }
public class SeqenecRoutine { private enum STATE { IDLE, WAIT } protected DeviceTimer counter = new DeviceTimer(); protected DeviceTimer delayTimer = new DeviceTimer(); private int _id; private Stack<int> _steps = new Stack<int>(); private STATE state; private int loop; private int loopCount; private int loopID; private DeviceTimer timer = new DeviceTimer(); protected RoutineResult RoutineToken = new RoutineResult { Result = RoutineState.Running }; public int TokenId => _id; public int LoopCounter => loop; public int LoopTotalTime => loopCount; public int Elapsed => (int)(timer.GetElapseTime() / 1000.0); public void Reset() { _id = 0; _steps.Clear(); loop = 0; loopCount = 0; state = STATE.IDLE; counter.Start(360000.0); RoutineToken.Result = RoutineState.Running; } protected void PerformRoutineStep(int id, Func<RoutineState> execution, RoutineResult result) { if (Acitve(id)) { result.Result = execution(); } } public void StopLoop() { loop = loopCount; } public Tuple<bool, Result> Loop<T>(T id, Func<bool> func, int count) { int id2 = Convert.ToInt32(id); bool flag = Acitve(id2); if (flag) { if (!func()) { return Tuple.Create(flag, Result.FAIL); } loopID = id2; loopCount = count; next(); return Tuple.Create(item1: true, Result.RUN); } return Tuple.Create(item1: false, Result.RUN); } public Tuple<bool, Result> EndLoop<T>(T id, Func<bool> func) { int id2 = Convert.ToInt32(id); bool flag = Acitve(id2); if (flag) { if (++loop >= loopCount) { if (!func()) { return Tuple.Create(flag, Result.FAIL); } loop = 0; loopCount = 0; next(); return Tuple.Create(item1: true, Result.RUN); } next(loopID); return Tuple.Create(item1: true, Result.RUN); } return Tuple.Create(item1: false, Result.RUN); } public Tuple<bool, Result> ExecuteAndWait<T>(T id, IRoutine routine) { int id2 = Convert.ToInt32(id); if (Acitve(id2)) { if (state == STATE.IDLE) { switch (routine.Start()) { case Result.FAIL: return Tuple.Create(item1: true, Result.FAIL); case Result.DONE: next(); return Tuple.Create(item1: true, Result.DONE); } state = STATE.WAIT; } switch (routine.Monitor()) { case Result.DONE: next(); return Tuple.Create(item1: true, Result.DONE); case Result.FAIL: case Result.TIMEOUT: return Tuple.Create(item1: true, Result.FAIL); default: return Tuple.Create(item1: true, Result.RUN); } } return Tuple.Create(item1: false, Result.RUN); } public Tuple<bool, Result> ExecuteAndWait<T>(T id, List<IRoutine> routines) { int id2 = Convert.ToInt32(id); if (Acitve(id2)) { if (state == STATE.IDLE) { foreach (IRoutine routine in routines) { if (routine.Start() == Result.FAIL) { return Tuple.Create(item1: true, Result.FAIL); } } state = STATE.WAIT; } bool flag = false; bool flag2 = true; foreach (IRoutine routine2 in routines) { Result result = routine2.Monitor(); flag2 = flag2 && (result == Result.FAIL || result == Result.DONE); flag = flag || result == Result.FAIL; } if (flag2) { next(); if (flag) { return Tuple.Create(item1: true, Result.FAIL); } return Tuple.Create(item1: true, Result.DONE); } return Tuple.Create(item1: true, Result.RUN); } return Tuple.Create(item1: false, Result.RUN); } public Tuple<bool, Result> Check<T>(T id, Func<bool> func) { return Check(Check(Convert.ToInt32(id), func)); } public Tuple<bool, Result> Execute<T>(T id, Func<bool> func) { return Check(execute(Convert.ToInt32(id), func)); } public Tuple<bool, Result> Wait<T>(T id, Func<bool> func, double timeout = 2147483647.0) { return Check(wait(Convert.ToInt32(id), func, timeout)); } public Tuple<bool, Result> Wait<T>(T id, Func<bool?> func, double timeout = 2147483647.0) { return Check(wait(Convert.ToInt32(id), func, timeout)); } public Tuple<bool, Result> ExecuteAndWait<T>(T id, Func<bool> execute, Func<bool?> check, double timeout = 2147483647.0) { int id2 = Convert.ToInt32(id); bool flag = Acitve(id2); bool? flag2 = false; if (flag) { if (state == STATE.IDLE) { if (!execute()) { return Tuple.Create(flag, Result.FAIL); } timer.Start(timeout); state = STATE.WAIT; } flag2 = check(); if (!flag2.HasValue) { return Tuple.Create(flag, Result.FAIL); } if (flag2.Value) { next(); return Tuple.Create(item1: true, Result.RUN); } if (timer.IsTimeout()) { return Tuple.Create(item1: true, Result.TIMEOUT); } return Tuple.Create(item1: true, Result.RUN); } return Tuple.Create(item1: false, Result.RUN); } public Tuple<bool, Result> ExecuteAndWait<T>(T id, Func<bool> execute, Func<bool?> check, Func<double> time) { int id2 = Convert.ToInt32(id); bool num = Acitve(id2); bool? flag = false; double num2 = 0.0; if (num) { if (state == STATE.IDLE) { num2 = time(); if (!execute()) { return Tuple.Create(item1: true, Result.FAIL); } timer.Start(num2); state = STATE.WAIT; } flag = check(); if (!flag.HasValue) { return Tuple.Create(item1: true, Result.FAIL); } if (flag.Value) { next(); return Tuple.Create(item1: true, Result.RUN); } if (timer.IsTimeout()) { return Tuple.Create(item1: true, Result.TIMEOUT); } return Tuple.Create(item1: true, Result.RUN); } return Tuple.Create(item1: false, Result.RUN); } public Tuple<bool, Result> Wait<T>(T id, IRoutine rt) { int id2 = Convert.ToInt32(id); if (Acitve(id2)) { if (state == STATE.IDLE) { rt.Start(); state = STATE.WAIT; } Result item = rt.Monitor(); return Tuple.Create(item1: true, item); } return Tuple.Create(item1: false, Result.RUN); } public Tuple<bool, Result> Monitor<T>(T id, Func<bool> func, Func<bool> check, double time) { int id2 = Convert.ToInt32(id); if (Acitve(id2)) { if (state == STATE.IDLE) { if (func != null && !func()) { return Tuple.Create(item1: true, Result.FAIL); } timer.Start(time); state = STATE.WAIT; } if (!check()) { return Tuple.Create(item1: true, Result.FAIL); } if (timer.IsTimeout()) { next(); } return Tuple.Create(item1: true, Result.RUN); } return Tuple.Create(item1: false, Result.RUN); } public Tuple<bool, Result> Delay<T>(T id, Func<bool> func, double time) { int id2 = Convert.ToInt32(id); if (Acitve(id2)) { if (state == STATE.IDLE) { if (func != null && !func()) { return Tuple.Create(item1: true, Result.FAIL); } timer.Start(time); state = STATE.WAIT; } if (timer.IsTimeout()) { next(); } return Tuple.Create(item1: true, Result.RUN); } return Tuple.Create(item1: false, Result.RUN); } public Tuple<bool, Result> DelayCheck<T>(T id, Func<bool> func, double time) { int id2 = Convert.ToInt32(id); if (Acitve(id2)) { if (state == STATE.IDLE) { timer.Start(time); state = STATE.WAIT; } if (timer.IsTimeout()) { if (func != null && !func()) { return Tuple.Create(item1: true, Result.FAIL); } next(); } return Tuple.Create(item1: true, Result.RUN); } return Tuple.Create(item1: false, Result.RUN); } private Tuple<bool, bool> execute(int id, Func<bool> func) { bool num = Acitve(id); bool flag = false; if (num) { flag = func(); if (flag) { next(); } } return Tuple.Create(num, flag); } private Tuple<bool, bool> Check(int id, Func<bool> func) { bool num = Acitve(id); bool item = false; if (num) { item = func(); next(); } return Tuple.Create(num, item); } private Tuple<bool, bool, bool> wait(int id, Func<bool> func, double timeout = 2147483647.0) { bool num = Acitve(id); bool flag = false; bool item = false; if (num) { if (state == STATE.IDLE) { timer.Start(timeout); state = STATE.WAIT; } flag = func(); if (flag) { next(); } item = timer.IsTimeout(); } return Tuple.Create(num, flag, item); } private Tuple<bool, bool?, bool> wait(int id, Func<bool?> func, double timeout = 2147483647.0) { bool num = Acitve(id); bool? item = false; bool item2 = false; if (num) { if (state == STATE.IDLE) { timer.Start(timeout); state = STATE.WAIT; } item = func(); if (item.HasValue && item.Value) { next(); } item2 = timer.IsTimeout(); } return Tuple.Create(num, item, item2); } private Tuple<bool, Result> Check(Tuple<bool, bool> value) { if (value.Item1) { if (!value.Item2) { return Tuple.Create(item1: true, Result.FAIL); } return Tuple.Create(item1: true, Result.RUN); } return Tuple.Create(item1: false, Result.RUN); } private Tuple<bool, Result> Check(Tuple<bool, bool, bool> value) { if (value.Item1) { if (CheckTimeout(value)) { return Tuple.Create(item1: true, Result.TIMEOUT); } return Tuple.Create(item1: true, Result.RUN); } return Tuple.Create(item1: false, Result.RUN); } private Tuple<bool, Result> Check(Tuple<bool, bool?, bool> value) { if (value.Item1) { if (!value.Item2.HasValue) { return Tuple.Create(item1: true, Result.FAIL); } if (value.Item2 == false && value.Item3) { return Tuple.Create(item1: true, Result.TIMEOUT); } return Tuple.Create(item1: true, Result.RUN); } return Tuple.Create(item1: false, Result.RUN); } private bool CheckTimeout(Tuple<bool, bool, bool> value) { if (value.Item1 && !value.Item2) { return value.Item3; } return false; } private bool Acitve(int id) { if (_steps.Contains(id)) { return false; } _id = id; return true; } private void next() { _steps.Push(_id); state = STATE.IDLE; } private void next(int step) { while (_steps.Pop() != step) { } state = STATE.IDLE; } public void Delay(int id, double delaySeconds) { Tuple<bool, Result> tuple = Delay(id, () => true, delaySeconds * 1000.0); if (tuple.Item1 && tuple.Item2 == Result.RUN) { throw new RoutineBreakException(); } } public bool IsActived(int id) { return _steps.Contains(id); } }
public enum RoutineState { Running, Failed, Timeout, Finished }
public class RoutineResult { public RoutineState Result; public string ErrorMessage; }
public class RoutineBreakException : ApplicationException { public RoutineBreakException() { } public RoutineBreakException(string message) : base(message) { } }
public interface IRoutine { Result Start(params object[] objs); Result Monitor(); void Abort(); }
public enum Result { RUN, DONE, FAIL, TIMEOUT, VERIFYFAIL, PAUSE, SUCCEED }
比较难理解的代码 我要记录下 每天想想。