using System.Collections.Generic; using System.Threading; using Bro.Common.FSM; using System.Diagnostics; namespace Bro.Common.Procedure { /// /// 流程状态 /// public enum ProcStat { PSInit = 0, // 初始化 PSOpen, // 打开 PSRunning, // 运行 PSReset, // 重置, PSReseting, // 重置中 PSPause, // 暂停 PSClose, // 关闭 PSFnit // 销毁 } /// /// 处理流程基类 /// /// 说明: /// 工站,工位类都可继承此类 /// 定义如下动作 /// 1. 初始化/销毁 /// 2. 打开/关闭 /// 3. 读写 /// 4. 设置选项 /// 5. 事件订阅/取消 /// public abstract class ProcedureBase { #region 代理定义 // 状态变化事件 public delegate void StatChange(ProcedureBase procedure, ProcStat srcStat, ProcStat dstStat); #endregion #region 常量 // 线程默认等待时间(单位:毫秒) protected const int DFT_WAIT_INTERVAL = 200; #endregion #region 事件代理 // 流程状态变化 public StatChange StatChangeEvent; #endregion #region 属性 // 流程描述 public string Desp { get; set; } // 流程状态 public ProcStat Stat{ get { return curStat; } } #endregion #region 成员变量 // 流程状态机 protected SimpleFSM procFSM = new SimpleFSM(); // 流程状态 protected ProcStat curStat = ProcStat.PSInit; // 生产工序同步事件 protected AutoResetEvent waitEvent = new AutoResetEvent(false); // 输入队列 private Queue requestQueue = new Queue(); // 输入处理者 private List requestHandlers = new List(); #endregion #region 结构体 public ProcedureBase() { this.Desp = this.GetType().Name; // 设置默认的状态处理者 AddRequestHandler(this); RegistProcFSM(); } public ProcedureBase(SimpleFSM fsm) { this.Desp = this.GetType().Name; this.procFSM = fsm; // 设置默认的状态处理者 AddRequestHandler(this); RegistProcFSM(); } #endregion #region 外部接口 /// /// 暂停流程 /// public virtual void Pause() { Trace.TraceInformation("{0} Pause", Desp); var req = new ProcStatChangeReq(); req.TargetStat = ProcStat.PSPause; AddRequest(req); } /// /// 重置流程 /// public virtual void Reset() { Trace.TraceInformation("{0} Reset", Desp); var req = new ProcStatChangeReq(); req.TargetStat = ProcStat.PSReset; AddRequest(req); } /// /// 请求处理 /// /// public void AddRequest(IODataBase req) { if (null == req) { return; } lock (requestQueue) { // 设置输入处理者 req.Handlers = this.requestHandlers; requestQueue.Enqueue(req); } } #endregion #region 基础流程状态机 /// /// 注册基本状态处理 /// protected virtual bool RegistProcFSM() { int iRet = 0; if ( null == procFSM ) { return false; } iRet += procFSM.Regist((int)ProcStat.PSInit, DoInit) ? 0 : 1; iRet += procFSM.Regist((int)ProcStat.PSOpen, DoOpen) ? 0 : 1; iRet += procFSM.Regist((int)ProcStat.PSClose, DoClose) ? 0 : 1; iRet += procFSM.Regist((int)ProcStat.PSRunning, DoRunning) ? 0 : 1; iRet += procFSM.Regist((int)ProcStat.PSReset, DoReset) ? 0 : 1; iRet += procFSM.Regist((int)ProcStat.PSReseting, DoReseting) ? 0 : 1; iRet += procFSM.Regist((int)ProcStat.PSPause, DoPause) ? 0 : 1; iRet += procFSM.Regist((int)ProcStat.PSFnit, DoFnit) ? 0 : 1; // 设置初始状态 SetState(ProcStat.PSInit); return (iRet == 0); } /// /// 初始化 /// public virtual void DoInit() { Trace.TraceInformation("{0} DoInit", Desp); ClearIOData(); SetState(ProcStat.PSOpen); } /// /// 销毁 /// public virtual void DoFnit() { Trace.TraceInformation("{0} DoFnit", Desp); } /// /// 开始 /// public virtual void DoOpen() { Trace.TraceInformation("{0} DoOpen", Desp); SetState(ProcStat.PSRunning); } /// /// 停止 /// public virtual void DoClose() { Trace.TraceInformation("{0} DoClose", this.GetType().Name); SetState(ProcStat.PSFnit); } /// /// 重置 /// public virtual void DoReset() { Trace.TraceInformation("{0} DoReset", this.GetType().Name); SetState(ProcStat.PSReseting); } /// /// 重置中 /// public virtual void DoReseting() { Trace.TraceInformation("{0} DoReseting", this.GetType().Name); SetState(ProcStat.PSRunning); } /// /// 暂停 /// public virtual void DoPause() { // 等待 waitEvent.WaitOne(DFT_WAIT_INTERVAL); } /// /// 就绪 /// public virtual void DoRunning() { // TODO:流程就绪,主处理 } #endregion #region 请求处理 /// /// 状态转变请求 /// /// /// protected bool HandleRequest(ProcStatChangeReq req) { Trace.TraceInformation("{0} HandleRequest cur stat:{1} target:{2}", Desp, GetStatDesp(Stat), GetStatDesp(req.TargetStat)); if ( req.TargetStat == Stat ) { Trace.TraceWarning("{0} HandleRequest fail, already in {1}", Desp, GetStatDesp(req.TargetStat)); return true; } if ( ProcStat.PSRunning != this.Stat ) { Trace.TraceWarning("{0} not running, can't turn to {1}", Desp, GetStatDesp(req.TargetStat)); return true; } SetState(req.TargetStat); return true; } #endregion #region 其他方法 /// /// 运行 /// public virtual void Run() { procFSM.Run(); Routine(); } /// /// 流程每次运行的例程 /// protected virtual void Routine() { // 处理请求 HandleRequests(); } /// /// 设置状态 /// /// protected internal void SetState(ProcStat stat) { var srcStat = GetStatDesp(curStat); var dstStat = GetStatDesp(stat); var tempStat = curStat; curStat = stat; if (null == procFSM) { return; } Trace.TraceInformation("{0} stat [{1}]-->[{2}]", Desp, srcStat, dstStat); procFSM.SetStat((int)stat); // 通知流程状态变化 if (null != StatChangeEvent) { StatChangeEvent(this, tempStat, stat); } } /// /// 设置输入处理者 /// /// public void AddRequestHandler(object handler) { requestHandlers.Add(handler); } /// /// 处理输入 /// protected void HandleRequests() { var req = NextReq(); if ( null == req ) { return; } Trace.TraceInformation("[{0}] HandleRequest {1} ", Desp, req.GetType().Name); // 输入处理派遣 req.Dispatch(); } /// /// 获取下个输入 /// /// protected IODataBase NextReq() { return NextData(requestQueue); } /// /// 添加数据 /// /// /// protected void AddQueue(IODataBase data, Queue dataQueue) { if ( null == data || null == dataQueue ) { return; } lock(dataQueue) { dataQueue.Enqueue(data); } } /// /// 获取下个数据 /// /// /// protected IODataBase NextData(Queue dataQueue) { IODataBase ioData = null; lock(dataQueue) { if ( dataQueue.Count > 0 ) { ioData = dataQueue.Dequeue(); } } return ioData; } /// /// 情空输入数据 /// protected void ClearIOData() { lock(requestQueue) { requestQueue.Clear(); } } /// /// 获取状态描述 /// /// /// private string GetStatDesp(ProcStat procStat) { var desp = ""; switch (procStat) { case ProcStat.PSInit: desp = "PSInit"; break; case ProcStat.PSFnit: desp = "PSFnit"; break; case ProcStat.PSOpen: desp = "PSOpen"; break; case ProcStat.PSClose: desp = "PSClose"; break; case ProcStat.PSRunning: desp = "PSRunning"; break; case ProcStat.PSPause: desp = "PSPause"; break; case ProcStat.PSReset: desp = "PSReset"; break; case ProcStat.PSReseting: desp = "PSReseting"; break; default: desp = "Unknow"; break; } return desp; } #endregion } }