BasicMethod.StateMachine — 状态机框架
定位:BasicMethod.Map 的状态机基础框架模块
核心能力:4 种状态转换模式 + 4 个通用组件 + 2 个预定义状态枚举
设计哲学:零外部依赖,纯 .NET 基础类库
适用场景:工作流编排、执行单元生命周期管理、事件驱动协调、线性处理管道
1. 概述
BasicMethod.StateMachine 是一个零外部依赖的通用状态机基础框架。它解决了工作流/执行单元在不同场景下需要不同状态转换模式的问题,提供四种正交的状态机模式,覆盖从简单的条件转换到复杂的异步事件驱动的全场景。
问题
传统方式下,每个需要状态管理的模块都要自行实现状态转换逻辑,导致大量重复代码:
#mermaid-svg-gJtO3HYgBd7O5FA3{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gJtO3HYgBd7O5FA3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gJtO3HYgBd7O5FA3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gJtO3HYgBd7O5FA3 .error-icon{fill:#552222;}#mermaid-svg-gJtO3HYgBd7O5FA3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gJtO3HYgBd7O5FA3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gJtO3HYgBd7O5FA3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gJtO3HYgBd7O5FA3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gJtO3HYgBd7O5FA3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gJtO3HYgBd7O5FA3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gJtO3HYgBd7O5FA3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gJtO3HYgBd7O5FA3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gJtO3HYgBd7O5FA3 .marker.cross{stroke:#333333;}#mermaid-svg-gJtO3HYgBd7O5FA3 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gJtO3HYgBd7O5FA3 p{margin:0;}#mermaid-svg-gJtO3HYgBd7O5FA3 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-gJtO3HYgBd7O5FA3 .cluster-label text{fill:#333;}#mermaid-svg-gJtO3HYgBd7O5FA3 .cluster-label span{color:#333;}#mermaid-svg-gJtO3HYgBd7O5FA3 .cluster-label span p{background-color:transparent;}#mermaid-svg-gJtO3HYgBd7O5FA3 .label text,#mermaid-svg-gJtO3HYgBd7O5FA3 span{fill:#333;color:#333;}#mermaid-svg-gJtO3HYgBd7O5FA3 .node rect,#mermaid-svg-gJtO3HYgBd7O5FA3 .node circle,#mermaid-svg-gJtO3HYgBd7O5FA3 .node ellipse,#mermaid-svg-gJtO3HYgBd7O5FA3 .node polygon,#mermaid-svg-gJtO3HYgBd7O5FA3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gJtO3HYgBd7O5FA3 .rough-node .label text,#mermaid-svg-gJtO3HYgBd7O5FA3 .node .label text,#mermaid-svg-gJtO3HYgBd7O5FA3 .image-shape .label,#mermaid-svg-gJtO3HYgBd7O5FA3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-gJtO3HYgBd7O5FA3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gJtO3HYgBd7O5FA3 .rough-node .label,#mermaid-svg-gJtO3HYgBd7O5FA3 .node .label,#mermaid-svg-gJtO3HYgBd7O5FA3 .image-shape .label,#mermaid-svg-gJtO3HYgBd7O5FA3 .icon-shape .label{text-align:center;}#mermaid-svg-gJtO3HYgBd7O5FA3 .node.clickable{cursor:pointer;}#mermaid-svg-gJtO3HYgBd7O5FA3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gJtO3HYgBd7O5FA3 .arrowheadPath{fill:#333333;}#mermaid-svg-gJtO3HYgBd7O5FA3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gJtO3HYgBd7O5FA3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gJtO3HYgBd7O5FA3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gJtO3HYgBd7O5FA3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gJtO3HYgBd7O5FA3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gJtO3HYgBd7O5FA3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gJtO3HYgBd7O5FA3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gJtO3HYgBd7O5FA3 .cluster text{fill:#333;}#mermaid-svg-gJtO3HYgBd7O5FA3 .cluster span{color:#333;}#mermaid-svg-gJtO3HYgBd7O5FA3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gJtO3HYgBd7O5FA3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gJtO3HYgBd7O5FA3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-gJtO3HYgBd7O5FA3 .icon-shape,#mermaid-svg-gJtO3HYgBd7O5FA3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gJtO3HYgBd7O5FA3 .icon-shape p,#mermaid-svg-gJtO3HYgBd7O5FA3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gJtO3HYgBd7O5FA3 .icon-shape .label rect,#mermaid-svg-gJtO3HYgBd7O5FA3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gJtO3HYgBd7O5FA3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gJtO3HYgBd7O5FA3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gJtO3HYgBd7O5FA3 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
❌ 传统方式:每模块自实现
模块 A自实现状态机
模块 B自实现状态机
模块 C自实现状态机
模块 D自实现状态机
解决方案
基于四种正交的状态机模式 + 通用组件,统一状态管理:
#mermaid-svg-GmdFG1vdR0xms9HK{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GmdFG1vdR0xms9HK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GmdFG1vdR0xms9HK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GmdFG1vdR0xms9HK .error-icon{fill:#552222;}#mermaid-svg-GmdFG1vdR0xms9HK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GmdFG1vdR0xms9HK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GmdFG1vdR0xms9HK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GmdFG1vdR0xms9HK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GmdFG1vdR0xms9HK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GmdFG1vdR0xms9HK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GmdFG1vdR0xms9HK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GmdFG1vdR0xms9HK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GmdFG1vdR0xms9HK .marker.cross{stroke:#333333;}#mermaid-svg-GmdFG1vdR0xms9HK svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GmdFG1vdR0xms9HK p{margin:0;}#mermaid-svg-GmdFG1vdR0xms9HK .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-GmdFG1vdR0xms9HK .cluster-label text{fill:#333;}#mermaid-svg-GmdFG1vdR0xms9HK .cluster-label span{color:#333;}#mermaid-svg-GmdFG1vdR0xms9HK .cluster-label span p{background-color:transparent;}#mermaid-svg-GmdFG1vdR0xms9HK .label text,#mermaid-svg-GmdFG1vdR0xms9HK span{fill:#333;color:#333;}#mermaid-svg-GmdFG1vdR0xms9HK .node rect,#mermaid-svg-GmdFG1vdR0xms9HK .node circle,#mermaid-svg-GmdFG1vdR0xms9HK .node ellipse,#mermaid-svg-GmdFG1vdR0xms9HK .node polygon,#mermaid-svg-GmdFG1vdR0xms9HK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GmdFG1vdR0xms9HK .rough-node .label text,#mermaid-svg-GmdFG1vdR0xms9HK .node .label text,#mermaid-svg-GmdFG1vdR0xms9HK .image-shape .label,#mermaid-svg-GmdFG1vdR0xms9HK .icon-shape .label{text-anchor:middle;}#mermaid-svg-GmdFG1vdR0xms9HK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GmdFG1vdR0xms9HK .rough-node .label,#mermaid-svg-GmdFG1vdR0xms9HK .node .label,#mermaid-svg-GmdFG1vdR0xms9HK .image-shape .label,#mermaid-svg-GmdFG1vdR0xms9HK .icon-shape .label{text-align:center;}#mermaid-svg-GmdFG1vdR0xms9HK .node.clickable{cursor:pointer;}#mermaid-svg-GmdFG1vdR0xms9HK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GmdFG1vdR0xms9HK .arrowheadPath{fill:#333333;}#mermaid-svg-GmdFG1vdR0xms9HK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GmdFG1vdR0xms9HK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GmdFG1vdR0xms9HK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GmdFG1vdR0xms9HK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GmdFG1vdR0xms9HK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GmdFG1vdR0xms9HK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GmdFG1vdR0xms9HK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GmdFG1vdR0xms9HK .cluster text{fill:#333;}#mermaid-svg-GmdFG1vdR0xms9HK .cluster span{color:#333;}#mermaid-svg-GmdFG1vdR0xms9HK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GmdFG1vdR0xms9HK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GmdFG1vdR0xms9HK rect.text{fill:none;stroke-width:0;}#mermaid-svg-GmdFG1vdR0xms9HK .icon-shape,#mermaid-svg-GmdFG1vdR0xms9HK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GmdFG1vdR0xms9HK .icon-shape p,#mermaid-svg-GmdFG1vdR0xms9HK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GmdFG1vdR0xms9HK .icon-shape .label rect,#mermaid-svg-GmdFG1vdR0xms9HK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GmdFG1vdR0xms9HK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GmdFG1vdR0xms9HK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GmdFG1vdR0xms9HK :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
✅ StateMachine 方式:统一框架
StateMachine统一框架
Conditional条件转换
Sequential顺序处理
Lifecycle生命周期
AsyncEvent异步事件
通用组件Store/Pause/Scope/Session
2. 四种状态机模式
2.1 ConditionalStateMachine — 条件转换状态机
核心特征:通过 TryTransitionTo/TryTransitionFrom 进行状态转换,支持条件验证和时间追踪。
适用场景:执行状态管理(Pending→Running→Completed/Faulted)、工作流编排、资源生命周期管理。
状态转换图:
#mermaid-svg-WizoKVlDztOxwWpn{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WizoKVlDztOxwWpn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WizoKVlDztOxwWpn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WizoKVlDztOxwWpn .error-icon{fill:#552222;}#mermaid-svg-WizoKVlDztOxwWpn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WizoKVlDztOxwWpn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WizoKVlDztOxwWpn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WizoKVlDztOxwWpn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WizoKVlDztOxwWpn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WizoKVlDztOxwWpn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WizoKVlDztOxwWpn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WizoKVlDztOxwWpn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WizoKVlDztOxwWpn .marker.cross{stroke:#333333;}#mermaid-svg-WizoKVlDztOxwWpn svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WizoKVlDztOxwWpn p{margin:0;}#mermaid-svg-WizoKVlDztOxwWpn defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-WizoKVlDztOxwWpn g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-WizoKVlDztOxwWpn g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-WizoKVlDztOxwWpn g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-WizoKVlDztOxwWpn g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-WizoKVlDztOxwWpn g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-WizoKVlDztOxwWpn .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-WizoKVlDztOxwWpn .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-WizoKVlDztOxwWpn .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-WizoKVlDztOxwWpn .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-WizoKVlDztOxwWpn .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-WizoKVlDztOxwWpn .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-WizoKVlDztOxwWpn .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-WizoKVlDztOxwWpn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WizoKVlDztOxwWpn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WizoKVlDztOxwWpn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WizoKVlDztOxwWpn .edgeLabel .label text{fill:#333;}#mermaid-svg-WizoKVlDztOxwWpn .label div .edgeLabel{color:#333;}#mermaid-svg-WizoKVlDztOxwWpn .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-WizoKVlDztOxwWpn .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-WizoKVlDztOxwWpn .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-WizoKVlDztOxwWpn .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-WizoKVlDztOxwWpn .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-WizoKVlDztOxwWpn .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WizoKVlDztOxwWpn .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WizoKVlDztOxwWpn #statediagram-barbEnd{fill:#333333;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WizoKVlDztOxwWpn .cluster-label,#mermaid-svg-WizoKVlDztOxwWpn .nodeLabel{color:#131300;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-WizoKVlDztOxwWpn .note-edge{stroke-dasharray:5;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-note text{fill:black;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram-note .nodeLabel{color:black;}#mermaid-svg-WizoKVlDztOxwWpn .statediagram .edgeLabel{color:red;}#mermaid-svg-WizoKVlDztOxwWpn #dependencyStart,#mermaid-svg-WizoKVlDztOxwWpn #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-WizoKVlDztOxwWpn .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WizoKVlDztOxwWpn :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
初始化
TryTransitionTo(StateA)
TryTransitionTo(StateB, condition)
TryTransitionFrom(StateA, StateC)
TryTransitionFrom(StateB, StateD)
Reset
Reset
InitialState
StateA
StateB
StateC
StateD
条件验证:condition(currentState) == true才允许转换
使用示例:
enum Status { Idle, Running, Completed, Faulted }
var sm = new ConditionalStateMachine<Status>(Status.Idle);
// 无条件转换
sm.TryTransitionTo(Status.Running); // true
// 条件转换:仅当当前状态为 Running 时才允许
sm.TryTransitionTo(Status.Completed, s => s == Status.Running); // true
// 期望状态验证:仅当当前状态为 Running 时才允许转换到 Faulted
sm.TryTransitionFrom(Status.Running, Status.Faulted); // false(当前是 Completed)
// 状态查询
Console.WriteLine(sm.CurrentState); // Completed
Console.WriteLine(sm.IsFinished); // false(需子类重写)
Console.WriteLine(sm.StartTime); // 初始化时间
与 LifecycleStateMachine 的区别:
| 转换方式 | 条件验证 TryXxx | 操作驱动 Permit/Fire |
| 非法转换 | 返回 false | 抛出 InvalidTransitionException |
| 时间追踪 | 内置 StartTime/EndTime | 无 |
| 状态快照 | GetSnapshot() | 无 |
2.2 SequentialStateMachine — 顺序处理状态机
核心特征:处理逐个输入的字符/Token 流,根据当前状态决定转换和累积输出。
适用场景:CommandTokenizer(char→token列表)、RestoreJsonObject(char→JSON)、ParseCondition(char→解析结果)、FindAdapter(Type→适配器)等线性处理管道。
处理流程:
累积上下文SequentialStateMachine调用方累积上下文SequentialStateMachine调用方#mermaid-svg-4PWBuDhOU2Bj09C3{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4PWBuDhOU2Bj09C3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4PWBuDhOU2Bj09C3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4PWBuDhOU2Bj09C3 .error-icon{fill:#552222;}#mermaid-svg-4PWBuDhOU2Bj09C3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4PWBuDhOU2Bj09C3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4PWBuDhOU2Bj09C3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4PWBuDhOU2Bj09C3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4PWBuDhOU2Bj09C3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4PWBuDhOU2Bj09C3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4PWBuDhOU2Bj09C3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4PWBuDhOU2Bj09C3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4PWBuDhOU2Bj09C3 .marker.cross{stroke:#333333;}#mermaid-svg-4PWBuDhOU2Bj09C3 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4PWBuDhOU2Bj09C3 p{margin:0;}#mermaid-svg-4PWBuDhOU2Bj09C3 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-4PWBuDhOU2Bj09C3 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-4PWBuDhOU2Bj09C3 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-4PWBuDhOU2Bj09C3 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-4PWBuDhOU2Bj09C3 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-4PWBuDhOU2Bj09C3 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-4PWBuDhOU2Bj09C3 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-4PWBuDhOU2Bj09C3 .sequenceNumber{fill:white;}#mermaid-svg-4PWBuDhOU2Bj09C3 #sequencenumber{fill:#333;}#mermaid-svg-4PWBuDhOU2Bj09C3 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-4PWBuDhOU2Bj09C3 .messageText{fill:#333;stroke:none;}#mermaid-svg-4PWBuDhOU2Bj09C3 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-4PWBuDhOU2Bj09C3 .labelText,#mermaid-svg-4PWBuDhOU2Bj09C3 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-4PWBuDhOU2Bj09C3 .loopText,#mermaid-svg-4PWBuDhOU2Bj09C3 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-4PWBuDhOU2Bj09C3 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-4PWBuDhOU2Bj09C3 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-4PWBuDhOU2Bj09C3 .noteText,#mermaid-svg-4PWBuDhOU2Bj09C3 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-4PWBuDhOU2Bj09C3 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-4PWBuDhOU2Bj09C3 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-4PWBuDhOU2Bj09C3 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-4PWBuDhOU2Bj09C3 .actorPopupMenu{position:absolute;}#mermaid-svg-4PWBuDhOU2Bj09C3 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-4PWBuDhOU2Bj09C3 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-4PWBuDhOU2Bj09C3 .actor-man circle,#mermaid-svg-4PWBuDhOU2Bj09C3 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-4PWBuDhOU2Bj09C3 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}alt[精确匹配][默认匹配][无匹配]loop[逐个输入]构造(initialState)When(StateA, condition, StateB, action)When(StateB, condition, StateC, action)Otherwise(StateDefault, action)Feed(input)查找匹配的 Transition执行 When 规则执行 Otherwise 规则return false执行 Action(input, context)return trueComplete(resultSelector)返回最终结果
使用示例:
// 示例:简单的 Tokenizer
enum TokenizerState { NORMAL, IN_QUOTE }
var sm = new SequentialStateMachine<char, StringBuilder, List<string>>(
(int)TokenizerState.NORMAL);
// 注册转换规则
sm.When((int)TokenizerState.NORMAL, c => c == '"',
(int)TokenizerState.IN_QUOTE);
sm.When((int)TokenizerState.NORMAL, c => char.IsWhiteSpace(c),
(int)TokenizerState.NORMAL, (c, ctx) => FlushToken(ctx));
sm.When((int)TokenizerState.NORMAL, c => true,
(int)TokenizerState.NORMAL, (c, ctx) => ctx.Append(c));
sm.When((int)TokenizerState.IN_QUOTE, c => c == '"',
(int)TokenizerState.NORMAL, (c, ctx) => FlushToken(ctx));
sm.Otherwise((int)TokenizerState.NORMAL);
// 处理输入
foreach (char c in input) sm.Feed(c);
// 获取结果
var tokens = sm.Complete(ctx => ExtractTokens(ctx));
2.3 LifecycleStateMachine — 生命周期状态机
核心特征:通过操作触发状态转换,伴随副作用,可检测非法转换。
适用场景:MiddlewarePipeline(Use/Build/Clear)、CommandRouter(Register/Unregister/SetActive)等具有明确生命周期阶段的管理类。
状态转换图:
#mermaid-svg-Sv5fIT531wBU5G3u{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Sv5fIT531wBU5G3u .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Sv5fIT531wBU5G3u .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Sv5fIT531wBU5G3u .error-icon{fill:#552222;}#mermaid-svg-Sv5fIT531wBU5G3u .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Sv5fIT531wBU5G3u .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Sv5fIT531wBU5G3u .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Sv5fIT531wBU5G3u .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Sv5fIT531wBU5G3u .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Sv5fIT531wBU5G3u .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Sv5fIT531wBU5G3u .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Sv5fIT531wBU5G3u .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Sv5fIT531wBU5G3u .marker.cross{stroke:#333333;}#mermaid-svg-Sv5fIT531wBU5G3u svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Sv5fIT531wBU5G3u p{margin:0;}#mermaid-svg-Sv5fIT531wBU5G3u defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-Sv5fIT531wBU5G3u g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-Sv5fIT531wBU5G3u g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-Sv5fIT531wBU5G3u g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-Sv5fIT531wBU5G3u g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-Sv5fIT531wBU5G3u g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-Sv5fIT531wBU5G3u .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-Sv5fIT531wBU5G3u .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-Sv5fIT531wBU5G3u .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-Sv5fIT531wBU5G3u .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Sv5fIT531wBU5G3u .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-Sv5fIT531wBU5G3u .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-Sv5fIT531wBU5G3u .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-Sv5fIT531wBU5G3u .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Sv5fIT531wBU5G3u .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Sv5fIT531wBU5G3u .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Sv5fIT531wBU5G3u .edgeLabel .label text{fill:#333;}#mermaid-svg-Sv5fIT531wBU5G3u .label div .edgeLabel{color:#333;}#mermaid-svg-Sv5fIT531wBU5G3u .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-Sv5fIT531wBU5G3u .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-Sv5fIT531wBU5G3u .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-Sv5fIT531wBU5G3u .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-Sv5fIT531wBU5G3u .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-Sv5fIT531wBU5G3u .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Sv5fIT531wBU5G3u .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Sv5fIT531wBU5G3u #statediagram-barbEnd{fill:#333333;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Sv5fIT531wBU5G3u .cluster-label,#mermaid-svg-Sv5fIT531wBU5G3u .nodeLabel{color:#131300;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-Sv5fIT531wBU5G3u .note-edge{stroke-dasharray:5;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-note text{fill:black;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram-note .nodeLabel{color:black;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagram .edgeLabel{color:red;}#mermaid-svg-Sv5fIT531wBU5G3u #dependencyStart,#mermaid-svg-Sv5fIT531wBU5G3u #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-Sv5fIT531wBU5G3u .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Sv5fIT531wBU5G3u :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
初始化
PermitReentry(Use)注册中间件
Permit(Build)构建管道
Permit(Clear)清空管道
PermitReentry(Use)❌ 抛出异常
UNBUILT
BUILT
Permit: 状态变更 + 副作用PermitReentry: 状态不变 + 副作用
使用示例:
enum PipelineOp { Use, Build, Clear }
var sm = new LifecycleStateMachine<PipelineOp>(UNBUILT);
// 注册许可转换
sm.Permit(UNBUILT, PipelineOp.Use, UNBUILT, () => middlewares.Add(mw));
sm.Permit(UNBUILT, PipelineOp.Build, BUILT, () => BuildPipeline());
sm.Permit(BUILT, PipelineOp.Clear, UNBUILT, () => ClearPipeline());
// 执行操作
sm.Fire(PipelineOp.Use); // 成功,状态不变
sm.Fire(PipelineOp.Build); // 成功,状态变为 BUILT
sm.Fire(PipelineOp.Build); // 抛出 InvalidTransitionException!
// 安全检查
if (sm.CanFire(PipelineOp.Clear))
sm.Fire(PipelineOp.Clear);
// 获取允许的操作
var allowed = sm.GetAllowedOperations();
2.4 AsyncEventStateMachine — 异步事件状态机
核心特征:等待外部事件触发,支持超时和取消。
适用场景:WaitAsync(等待控件状态变化)、事件驱动的异步协调、UI 自动化等待。
等待流程:
外部事件源超时计时器AsyncEventStateMachine调用方外部事件源超时计时器AsyncEventStateMachine调用方#mermaid-svg-aOrk6als6OmAZC55{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-aOrk6als6OmAZC55 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-aOrk6als6OmAZC55 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-aOrk6als6OmAZC55 .error-icon{fill:#552222;}#mermaid-svg-aOrk6als6OmAZC55 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aOrk6als6OmAZC55 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-aOrk6als6OmAZC55 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aOrk6als6OmAZC55 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aOrk6als6OmAZC55 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-aOrk6als6OmAZC55 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aOrk6als6OmAZC55 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aOrk6als6OmAZC55 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aOrk6als6OmAZC55 .marker.cross{stroke:#333333;}#mermaid-svg-aOrk6als6OmAZC55 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aOrk6als6OmAZC55 p{margin:0;}#mermaid-svg-aOrk6als6OmAZC55 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-aOrk6als6OmAZC55 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-aOrk6als6OmAZC55 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-aOrk6als6OmAZC55 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-aOrk6als6OmAZC55 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-aOrk6als6OmAZC55 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-aOrk6als6OmAZC55 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-aOrk6als6OmAZC55 .sequenceNumber{fill:white;}#mermaid-svg-aOrk6als6OmAZC55 #sequencenumber{fill:#333;}#mermaid-svg-aOrk6als6OmAZC55 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-aOrk6als6OmAZC55 .messageText{fill:#333;stroke:none;}#mermaid-svg-aOrk6als6OmAZC55 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-aOrk6als6OmAZC55 .labelText,#mermaid-svg-aOrk6als6OmAZC55 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-aOrk6als6OmAZC55 .loopText,#mermaid-svg-aOrk6als6OmAZC55 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-aOrk6als6OmAZC55 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-aOrk6als6OmAZC55 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-aOrk6als6OmAZC55 .noteText,#mermaid-svg-aOrk6als6OmAZC55 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-aOrk6als6OmAZC55 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-aOrk6als6OmAZC55 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-aOrk6als6OmAZC55 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-aOrk6als6OmAZC55 .actorPopupMenu{position:absolute;}#mermaid-svg-aOrk6als6OmAZC55 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-aOrk6als6OmAZC55 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-aOrk6als6OmAZC55 .actor-man circle,#mermaid-svg-aOrk6als6OmAZC55 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-aOrk6als6OmAZC55 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}alt[事件匹配][超时][取消]WaitAsync(condition, timeoutMs, ct)状态: Idle → Waiting启动超时计时器返回 Task<TResult>OnEvent(eventArgs)condition(eventArgs) == true状态: Waiting → CompletedConvertEventToResult(eventArgs)Task 完成,返回 TResultOnTimeout()状态: Waiting → TimedOut抛出 TimeoutExceptionCancellationToken 触发状态: Waiting → Canceled抛出 OperationCanceledException
使用示例:
var awaiter = new AsyncEventStateMachine<EventArgs, bool>();
// 在另一个线程/事件处理器中触发
control.SomeEvent += (s, e) => awaiter.OnEvent(e);
// 等待事件发生(超时 5 秒)
try
{
var result = await awaiter.WaitAsync(
e => CheckCondition(control, expectedValue),
timeoutMs: 5000,
cancellationToken: ct);
Console.WriteLine("事件匹配成功");
}
catch (TimeoutException)
{
Console.WriteLine("等待超时");
}
catch (OperationCanceledException)
{
Console.WriteLine("等待被取消");
}
// 重置状态机,可重复使用
awaiter.Reset();
3. 预定义状态枚举
3.1 ExecutionStatus — 执行单元生命周期
描述一个执行单元(工作流、任务、操作等)从创建到完成的完整生命周期状态。
#mermaid-svg-CjA9NnyrsbZa2v4t{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CjA9NnyrsbZa2v4t .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CjA9NnyrsbZa2v4t .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CjA9NnyrsbZa2v4t .error-icon{fill:#552222;}#mermaid-svg-CjA9NnyrsbZa2v4t .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CjA9NnyrsbZa2v4t .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CjA9NnyrsbZa2v4t .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CjA9NnyrsbZa2v4t .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CjA9NnyrsbZa2v4t .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CjA9NnyrsbZa2v4t .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CjA9NnyrsbZa2v4t .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CjA9NnyrsbZa2v4t .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CjA9NnyrsbZa2v4t .marker.cross{stroke:#333333;}#mermaid-svg-CjA9NnyrsbZa2v4t svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CjA9NnyrsbZa2v4t p{margin:0;}#mermaid-svg-CjA9NnyrsbZa2v4t defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-CjA9NnyrsbZa2v4t g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-CjA9NnyrsbZa2v4t g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-CjA9NnyrsbZa2v4t g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-CjA9NnyrsbZa2v4t g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-CjA9NnyrsbZa2v4t g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-CjA9NnyrsbZa2v4t .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-CjA9NnyrsbZa2v4t .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-CjA9NnyrsbZa2v4t .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-CjA9NnyrsbZa2v4t .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-CjA9NnyrsbZa2v4t .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-CjA9NnyrsbZa2v4t .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-CjA9NnyrsbZa2v4t .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-CjA9NnyrsbZa2v4t .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CjA9NnyrsbZa2v4t .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CjA9NnyrsbZa2v4t .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CjA9NnyrsbZa2v4t .edgeLabel .label text{fill:#333;}#mermaid-svg-CjA9NnyrsbZa2v4t .label div .edgeLabel{color:#333;}#mermaid-svg-CjA9NnyrsbZa2v4t .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-CjA9NnyrsbZa2v4t .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-CjA9NnyrsbZa2v4t .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-CjA9NnyrsbZa2v4t .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-CjA9NnyrsbZa2v4t .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-CjA9NnyrsbZa2v4t .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CjA9NnyrsbZa2v4t .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CjA9NnyrsbZa2v4t #statediagram-barbEnd{fill:#333333;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CjA9NnyrsbZa2v4t .cluster-label,#mermaid-svg-CjA9NnyrsbZa2v4t .nodeLabel{color:#131300;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-CjA9NnyrsbZa2v4t .note-edge{stroke-dasharray:5;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-note text{fill:black;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram-note .nodeLabel{color:black;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagram .edgeLabel{color:red;}#mermaid-svg-CjA9NnyrsbZa2v4t #dependencyStart,#mermaid-svg-CjA9NnyrsbZa2v4t #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-CjA9NnyrsbZa2v4t .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CjA9NnyrsbZa2v4t :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
开始执行
取消
暂停
恢复
完成
失败
超时
取消
Pending
Running
Cancelled
Paused
Completed
Failed
Timeout
| Pending | 0 | 待执行 — 初始状态,尚未开始 |
| Running | 1 | 执行中 — 正在执行 |
| Completed | 2 | 已完成 — 执行成功 |
| Failed | 3 | 执行失败 — 发生错误 |
| Cancelled | 4 | 已取消 — 被外部取消 |
| Paused | 5 | 已暂停 — 执行被暂停(可恢复) |
| Timeout | 6 | 超时 — 超过指定时间未完成 |
3.2 NodeStatus — 工作流节点状态
描述工作流图中单个节点(步骤/活动)的执行状态,在 ExecutionStatus 基础上增加 Skipped 状态。
#mermaid-svg-fjCFuEbD9ixCLvEP{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fjCFuEbD9ixCLvEP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fjCFuEbD9ixCLvEP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fjCFuEbD9ixCLvEP .error-icon{fill:#552222;}#mermaid-svg-fjCFuEbD9ixCLvEP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fjCFuEbD9ixCLvEP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fjCFuEbD9ixCLvEP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fjCFuEbD9ixCLvEP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fjCFuEbD9ixCLvEP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fjCFuEbD9ixCLvEP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fjCFuEbD9ixCLvEP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fjCFuEbD9ixCLvEP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fjCFuEbD9ixCLvEP .marker.cross{stroke:#333333;}#mermaid-svg-fjCFuEbD9ixCLvEP svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fjCFuEbD9ixCLvEP p{margin:0;}#mermaid-svg-fjCFuEbD9ixCLvEP defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-fjCFuEbD9ixCLvEP g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-fjCFuEbD9ixCLvEP g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-fjCFuEbD9ixCLvEP g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-fjCFuEbD9ixCLvEP g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-fjCFuEbD9ixCLvEP g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-fjCFuEbD9ixCLvEP .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-fjCFuEbD9ixCLvEP .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-fjCFuEbD9ixCLvEP .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-fjCFuEbD9ixCLvEP .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-fjCFuEbD9ixCLvEP .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-fjCFuEbD9ixCLvEP .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-fjCFuEbD9ixCLvEP .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-fjCFuEbD9ixCLvEP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fjCFuEbD9ixCLvEP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fjCFuEbD9ixCLvEP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fjCFuEbD9ixCLvEP .edgeLabel .label text{fill:#333;}#mermaid-svg-fjCFuEbD9ixCLvEP .label div .edgeLabel{color:#333;}#mermaid-svg-fjCFuEbD9ixCLvEP .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-fjCFuEbD9ixCLvEP .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-fjCFuEbD9ixCLvEP .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-fjCFuEbD9ixCLvEP .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-fjCFuEbD9ixCLvEP .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-fjCFuEbD9ixCLvEP .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fjCFuEbD9ixCLvEP .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fjCFuEbD9ixCLvEP #statediagram-barbEnd{fill:#333333;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fjCFuEbD9ixCLvEP .cluster-label,#mermaid-svg-fjCFuEbD9ixCLvEP .nodeLabel{color:#131300;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-fjCFuEbD9ixCLvEP .note-edge{stroke-dasharray:5;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-note text{fill:black;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram-note .nodeLabel{color:black;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagram .edgeLabel{color:red;}#mermaid-svg-fjCFuEbD9ixCLvEP #dependencyStart,#mermaid-svg-fjCFuEbD9ixCLvEP #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-fjCFuEbD9ixCLvEP .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fjCFuEbD9ixCLvEP :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
开始执行
条件不满足
暂停
恢复
完成
失败
超时
Pending
Running
Skipped
Paused
Completed
Failed
Timeout
| Pending | 0 | 待执行 — 初始状态,尚未开始 |
| Running | 1 | 执行中 — 正在执行 |
| Completed | 2 | 已完成 — 执行成功 |
| Failed | 3 | 执行失败 — 发生错误 |
| Skipped | 4 | 已跳过 — 因条件不满足被跳过 |
| Paused | 5 | 已暂停 — 执行被暂停(可恢复) |
| Timeout | 6 | 超时 — 超过指定时间未完成 |
4. 通用组件
4.1 StateMachineStore — 状态机存储
管理多个 ConditionalStateMachine 实例,支持 TTL 自动清理。
var store = new StateMachineStore<ExecutionStatus>
{
MaxCapacity = 1000,
StateRetentionPeriod = TimeSpan.FromMinutes(5)
};
// 获取或创建状态机
var sm = store.GetOrCreate("execution-1");
sm.TryTransitionTo(ExecutionStatus.Running);
// 批量操作
store.CleanupFinished(); // 清理已结束的实例
var activeIds = store.GetActiveIds(); // 获取活跃实例
4.2 PauseHandle / PauseManager — 暂停/恢复控制
提供两级暂停控制:
- PauseHandle:单实例暂停/恢复,基于 TaskCompletionSource 实现高效异步等待
- PauseManager:全局暂停(Interlocked)+ 局部暂停(作用域)
// PauseHandle — 单实例暂停
var handle = new PauseHandle();
// 在异步方法中等待暂停
await handle.WaitIfPausedAsync(cancellationToken);
// 在其他地方控制暂停/恢复
handle.Pause();
handle.Resume();
// PauseManager — 全局/局部暂停
var pm = new PauseManager();
// 全局暂停
pm.RequestGlobalPause();
await pm.WaitForResumeAsync(null, CancellationToken.None);
// 局部暂停(作用域级别)
pm.RequestLocalPause("scope-1");
await pm.WaitForResumeAsync("scope-1", CancellationToken.None);
4.3 ScopeStateManager — 作用域状态管理器
支持嵌套作用域,每个作用域可独立管理状态。
var manager = new ScopeStateManager<ExecutionStatus>();
// 全局状态
manager.Global.TryTransitionTo(ExecutionStatus.Running);
// 创建作用域
var scope = manager.CreateScope("workflow-1");
scope.TryTransitionTo(ExecutionStatus.Running);
// 获取作用域
var s = manager.GetScope("workflow-1");
// 释放作用域
manager.ReleaseScope("workflow-1");
4.4 SessionManagerStateMachine — 会话管理器状态机
一站式会话管理:集成 ExecutionStateMachineBase + CancellationTokenSource + PauseManager。
var manager = new SessionManagerStateMachine<ExecutionStatus>(
maxCapacity: 1000,
retentionPeriod: TimeSpan.FromMinutes(5));
// 创建会话
var session = manager.CreateSession(
"session-1",
ExecutionStatus.Pending,
ExecutionStatus.Running,
ExecutionStatus.Paused);
session.MarkRunning(); // Pending → Running
session.MarkPaused(); // Running → Paused
session.MarkRunning(); // Paused → Running
session.MarkCompleted(); // Running → Completed
// 取消会话
manager.CancelSession("session-1");
// 清理已结束会话
manager.CleanupFinished();
// 暂停/恢复
manager.RequestGlobalPause();
manager.ResumeGlobalPause();
5. 基础设施
5.1 接口继承体系
#mermaid-svg-E1mMIdMg9c4N22JC{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-E1mMIdMg9c4N22JC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-E1mMIdMg9c4N22JC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-E1mMIdMg9c4N22JC .error-icon{fill:#552222;}#mermaid-svg-E1mMIdMg9c4N22JC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-E1mMIdMg9c4N22JC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-E1mMIdMg9c4N22JC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-E1mMIdMg9c4N22JC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-E1mMIdMg9c4N22JC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-E1mMIdMg9c4N22JC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-E1mMIdMg9c4N22JC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-E1mMIdMg9c4N22JC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-E1mMIdMg9c4N22JC .marker.cross{stroke:#333333;}#mermaid-svg-E1mMIdMg9c4N22JC svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-E1mMIdMg9c4N22JC p{margin:0;}#mermaid-svg-E1mMIdMg9c4N22JC g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-E1mMIdMg9c4N22JC g.classGroup text .title{font-weight:bolder;}#mermaid-svg-E1mMIdMg9c4N22JC .cluster-label text{fill:#333;}#mermaid-svg-E1mMIdMg9c4N22JC .cluster-label span{color:#333;}#mermaid-svg-E1mMIdMg9c4N22JC .cluster-label span p{background-color:transparent;}#mermaid-svg-E1mMIdMg9c4N22JC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-E1mMIdMg9c4N22JC .cluster text{fill:#333;}#mermaid-svg-E1mMIdMg9c4N22JC .cluster span{color:#333;}#mermaid-svg-E1mMIdMg9c4N22JC .nodeLabel,#mermaid-svg-E1mMIdMg9c4N22JC .edgeLabel{color:#131300;}#mermaid-svg-E1mMIdMg9c4N22JC .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-E1mMIdMg9c4N22JC .label text{fill:#131300;}#mermaid-svg-E1mMIdMg9c4N22JC .labelBkg{background:#ECECFF;}#mermaid-svg-E1mMIdMg9c4N22JC .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-E1mMIdMg9c4N22JC .classTitle{font-weight:bolder;}#mermaid-svg-E1mMIdMg9c4N22JC .node rect,#mermaid-svg-E1mMIdMg9c4N22JC .node circle,#mermaid-svg-E1mMIdMg9c4N22JC .node ellipse,#mermaid-svg-E1mMIdMg9c4N22JC .node polygon,#mermaid-svg-E1mMIdMg9c4N22JC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-E1mMIdMg9c4N22JC .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC g.clickable{cursor:pointer;}#mermaid-svg-E1mMIdMg9c4N22JC g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-E1mMIdMg9c4N22JC g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-E1mMIdMg9c4N22JC .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-E1mMIdMg9c4N22JC .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-E1mMIdMg9c4N22JC .dashed-line{stroke-dasharray:3;}#mermaid-svg-E1mMIdMg9c4N22JC .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-E1mMIdMg9c4N22JC #compositionStart,#mermaid-svg-E1mMIdMg9c4N22JC .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC #compositionEnd,#mermaid-svg-E1mMIdMg9c4N22JC .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC #dependencyStart,#mermaid-svg-E1mMIdMg9c4N22JC .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC #dependencyStart,#mermaid-svg-E1mMIdMg9c4N22JC .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC #extensionStart,#mermaid-svg-E1mMIdMg9c4N22JC .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC #extensionEnd,#mermaid-svg-E1mMIdMg9c4N22JC .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC #aggregationStart,#mermaid-svg-E1mMIdMg9c4N22JC .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC #aggregationEnd,#mermaid-svg-E1mMIdMg9c4N22JC .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC #lollipopStart,#mermaid-svg-E1mMIdMg9c4N22JC .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC #lollipopEnd,#mermaid-svg-E1mMIdMg9c4N22JC .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-E1mMIdMg9c4N22JC .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-E1mMIdMg9c4N22JC .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-E1mMIdMg9c4N22JC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-E1mMIdMg9c4N22JC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-E1mMIdMg9c4N22JC :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}#mermaid-svg-E1mMIdMg9c4N22JC .IStateMachine>*{fill:#e3f2fd!important;stroke:#1565c0!important;}#mermaid-svg-E1mMIdMg9c4N22JC .IStateMachine span{fill:#e3f2fd!important;stroke:#1565c0!important;}#mermaid-svg-E1mMIdMg9c4N22JC .IConditionalStateMachine>*{fill:#e8f5e9!important;stroke:#2e7d32!important;}#mermaid-svg-E1mMIdMg9c4N22JC .IConditionalStateMachine span{fill:#e8f5e9!important;stroke:#2e7d32!important;}#mermaid-svg-E1mMIdMg9c4N22JC .IStateMachineStore>*{fill:#fff3e0!important;stroke:#e65100!important;}#mermaid-svg-E1mMIdMg9c4N22JC .IStateMachineStore span{fill:#fff3e0!important;stroke:#e65100!important;}#mermaid-svg-E1mMIdMg9c4N22JC .IPauseHandle>*{fill:#f3e5f5!important;stroke:#6a1b9a!important;}#mermaid-svg-E1mMIdMg9c4N22JC .IPauseHandle span{fill:#f3e5f5!important;stroke:#6a1b9a!important;}#mermaid-svg-E1mMIdMg9c4N22JC .IPauseManager>*{fill:#fce4ec!important;stroke:#c62828!important;}#mermaid-svg-E1mMIdMg9c4N22JC .IPauseManager span{fill:#fce4ec!important;stroke:#c62828!important;}#mermaid-svg-E1mMIdMg9c4N22JC .IScopeStateManager>*{fill:#e0f2f1!important;stroke:#00695c!important;}#mermaid-svg-E1mMIdMg9c4N22JC .IScopeStateManager span{fill:#e0f2f1!important;stroke:#00695c!important;}
继承
«interface»
IStateMachine<TState>
+CurrentState TState
+StateChanged event
+Reset(TState) : void
«interface»
IConditionalStateMachine<TState>
+StartTime DateTime
+EndTime DateTime?
+IsActive bool
+IsFinished bool
+TryTransitionTo(TState, Func<TState,bool>?) : bool
+TryTransitionFrom(TState, TState) : bool
«interface»
IStateMachineStore<TState>
+Count int
+MaxCapacity int
+StateRetentionPeriod TimeSpan
+GetOrCreate(string) : IConditionalStateMachine
+Get(string) : IConditionalStateMachine?
+Remove(string) : bool
+GetActiveIds() : IEnumerable
+GetAllIds() : IEnumerable
+CleanupFinished() : int
«interface»
IPauseHandle
+IsPaused bool
+Pause() : void
+Resume() : void
+WaitIfPausedAsync(CancellationToken) : Task
«interface»
IPauseManager
+IsGloballyPaused bool
+RequestGlobalPause() : void
+ResumeGlobalPause() : void
+IsLocallyPaused(string) : bool
+RequestLocalPause(string) : void
+ResumeLocalPause(string) : void
+WaitForResumeAsync(string?, CancellationToken, int) : Task
«interface»
IScopeStateManager<TState>
+Global IConditionalStateMachine
+CreateScope(string) : IConditionalStateMachine
+GetScope(string) : IConditionalStateMachine?
+ReleaseScope(string) : bool
+GetScopeNames() : IReadOnlyCollection
5.2 ExecutionStateMachineBase — 执行状态机基类
封装执行单元(会话/节点/任务等)的通用生命周期状态管理,提供语义化的 MarkXxx() 方法。
// 会话场景
var session = new ExecutionStateMachineBase<ExecutionStatus>(
"session-1", ExecutionStatus.Pending,
ExecutionStatus.Running, ExecutionStatus.Paused);
session.MarkRunning(); // Pending → Running(递增 ExecutionCount)
session.MarkPaused(); // Running → Paused
session.MarkRunning(); // Paused → Running(递增 ExecutionCount)
session.MarkCompleted(); // Running → Completed
Console.WriteLine(session.Status); // Completed
Console.WriteLine(session.IsFinished); // true
Console.WriteLine(session.ExecutionCount); // 2
Console.WriteLine(session.Duration); // 持续时间
// 节点场景(支持重试)
var node = new ExecutionStateMachineBase<NodeStatus>(
"node-1", NodeStatus.Pending,
NodeStatus.Running, NodeStatus.Paused);
node.MarkRunning(); // Pending → Running
node.MarkFailed("Error occurred");
Console.WriteLine(node.ErrorMessage); // "Error occurred"
node.Reset(NodeStatus.Pending);
node.MarkRunning(); // Pending → Running(重试)
node.MarkCompleted(); // Running → Completed
Console.WriteLine(node.ExecutionCount); // 2
5.3 StateRecord — 状态记录
在状态追踪基础上,额外记录动作执行历史(CompletedActions/FailedActions)。
var record = new StateRecord<ExecutionStatus>("workflow-1");
record.SetStatus(ExecutionStatus.Running);
record.SetCurrentAction("LoadData");
record.AddCompletedAction("LoadData");
record.Complete(ExecutionStatus.Completed);
Console.WriteLine(record.Duration); // 持续时间
Console.WriteLine(record.CompletedActions.Count); // 1
Console.WriteLine(record.FailedActions.Count); // 0
// 获取不可变快照
var snapshot = record.GetSnapshot();
5.4 StateChangeEmitter — 状态变更事件触发器
消除多个状态机实现中重复的 event 声明与触发模式,提供线程安全的事件订阅/触发。
// 所有状态机内部统一使用 StateChangeEmitter
// 对外暴露标准 event 接口
var sm = new ConditionalStateMachine<ExecutionStatus>();
sm.StateChanged += (sender, args) =>
{
Console.WriteLine($"{args.FromState} → {args.ToState}");
Console.WriteLine($"操作: {args.Operation}");
Console.WriteLine($"时间: {args.Timestamp}");
};
5.5 异常定义
| InvalidTransitionException | 非法状态转换 — 当状态机不允许指定的转换时抛出 |
| StateMachineConfigurationException | 状态机配置异常 — 当状态机配置存在冲突或错误时抛出 |
6. 与 Map 其他模块的关系
#mermaid-svg-rhoomq0yov3zpQgY{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rhoomq0yov3zpQgY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rhoomq0yov3zpQgY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rhoomq0yov3zpQgY .error-icon{fill:#552222;}#mermaid-svg-rhoomq0yov3zpQgY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rhoomq0yov3zpQgY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rhoomq0yov3zpQgY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rhoomq0yov3zpQgY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rhoomq0yov3zpQgY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rhoomq0yov3zpQgY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rhoomq0yov3zpQgY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rhoomq0yov3zpQgY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rhoomq0yov3zpQgY .marker.cross{stroke:#333333;}#mermaid-svg-rhoomq0yov3zpQgY svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rhoomq0yov3zpQgY p{margin:0;}#mermaid-svg-rhoomq0yov3zpQgY .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-rhoomq0yov3zpQgY .cluster-label text{fill:#333;}#mermaid-svg-rhoomq0yov3zpQgY .cluster-label span{color:#333;}#mermaid-svg-rhoomq0yov3zpQgY .cluster-label span p{background-color:transparent;}#mermaid-svg-rhoomq0yov3zpQgY .label text,#mermaid-svg-rhoomq0yov3zpQgY span{fill:#333;color:#333;}#mermaid-svg-rhoomq0yov3zpQgY .node rect,#mermaid-svg-rhoomq0yov3zpQgY .node circle,#mermaid-svg-rhoomq0yov3zpQgY .node ellipse,#mermaid-svg-rhoomq0yov3zpQgY .node polygon,#mermaid-svg-rhoomq0yov3zpQgY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rhoomq0yov3zpQgY .rough-node .label text,#mermaid-svg-rhoomq0yov3zpQgY .node .label text,#mermaid-svg-rhoomq0yov3zpQgY .image-shape .label,#mermaid-svg-rhoomq0yov3zpQgY .icon-shape .label{text-anchor:middle;}#mermaid-svg-rhoomq0yov3zpQgY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rhoomq0yov3zpQgY .rough-node .label,#mermaid-svg-rhoomq0yov3zpQgY .node .label,#mermaid-svg-rhoomq0yov3zpQgY .image-shape .label,#mermaid-svg-rhoomq0yov3zpQgY .icon-shape .label{text-align:center;}#mermaid-svg-rhoomq0yov3zpQgY .node.clickable{cursor:pointer;}#mermaid-svg-rhoomq0yov3zpQgY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rhoomq0yov3zpQgY .arrowheadPath{fill:#333333;}#mermaid-svg-rhoomq0yov3zpQgY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rhoomq0yov3zpQgY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rhoomq0yov3zpQgY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rhoomq0yov3zpQgY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rhoomq0yov3zpQgY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rhoomq0yov3zpQgY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rhoomq0yov3zpQgY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rhoomq0yov3zpQgY .cluster text{fill:#333;}#mermaid-svg-rhoomq0yov3zpQgY .cluster span{color:#333;}#mermaid-svg-rhoomq0yov3zpQgY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rhoomq0yov3zpQgY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rhoomq0yov3zpQgY rect.text{fill:none;stroke-width:0;}#mermaid-svg-rhoomq0yov3zpQgY .icon-shape,#mermaid-svg-rhoomq0yov3zpQgY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rhoomq0yov3zpQgY .icon-shape p,#mermaid-svg-rhoomq0yov3zpQgY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rhoomq0yov3zpQgY .icon-shape .label rect,#mermaid-svg-rhoomq0yov3zpQgY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rhoomq0yov3zpQgY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rhoomq0yov3zpQgY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rhoomq0yov3zpQgY :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
互补模块
互补
互补
互补
互补
互补
无关模块
Functor恒等传播
DecisionEngine
GraphFoundation
SortMent编排执行顺序
Transformers类型变换 A→B
Block显式上下文
Container执行单元
Declarative声明式描述
Queue队列调度
StateMachine状态转换管理4种模式+通用组件什么时候做什么
| Transformers | 互补 — Transformers 做类型变换 A→B,StateMachine 管理变换过程中的状态 |
| Block | 互补 — BlockContext 提供显式上下文,StateMachine 管理上下文的生命周期状态 |
| Container | 互补 — Container 提供执行单元,StateMachine 管理执行单元的状态转换 |
| Declarative | 互补 — Declarative 声明"有什么",StateMachine 管理"什么时候做什么" |
| Queue | 互补 — Queue 管理任务排队,StateMachine 管理队列中每个任务的状态 |
| Functor | 无关 — Functor 做恒等传播,StateMachine 做状态转换 |
| DecisionEngine | 无关 |
| GraphFoundation | 无关 |
| SortMent | 无关 — SortMent 编排执行顺序,StateMachine 管理单个执行单元的状态 |
7. 文件结构
StateMachine/
├── StateMachine.csproj # 项目文件(零外部依赖)
├── StateMachine.Abstractions.cs # 接口定义 + 异常定义
├── ExecutionStatus.cs # 执行状态枚举(7 种状态)
├── NodeStatus.cs # 节点状态枚举(7 种状态)
│
├── ConditionalStateMachine.cs # 条件转换状态机
├── SequentialStateMachine.cs # 顺序处理状态机
├── LifecycleStateMachine.cs # 生命周期状态机
├── AsyncEventStateMachine.cs # 异步事件状态机
│
├── ExecutionStateMachineBase.cs # 执行状态机基类(MarkXxx 语义化方法)
├── StateRecord.cs # 状态记录(动作执行历史追踪)
├── StateChangeEmitter.cs # 状态变更事件触发器
│
├── StateMachineStore.cs # 状态机存储(多实例管理 + TTL)
├── PauseHandle.cs # 暂停句柄(单实例暂停/恢复)
├── PauseManager.cs # 暂停管理器(全局/局部暂停)
├── ScopeStateManager.cs # 作用域状态管理器
├── SessionManagerStateMachine.cs # 会话管理器状态机
│
└── BasicMethod.StateMachine功能介绍.md # 本文档

