1. 状态机基础概念解析
状态机(Finite State Machine,FSM)是计算机科学中用于描述系统行为的数学模型。在任何给定时刻,系统只能处于有限数量的状态中的一种。当系统接收到输入(事件)时,它会根据当前状态和输入来决定是否转换到新状态以及执行哪些动作。
1.1 状态机核心要素
状态机由四个基本要素构成:
-
状态(State):系统可能处于的有限状态集合。例如在TVJ测试场景中,状态包括:
- Idle(空闲)
- VceHeating(VCE加热阶段)
- VfCooling(VF冷却采集阶段)
- CycleCompleted(周期完成)
-
事件(Event):触发状态转换的输入信号。在TVJ测试中,事件对应不同的marker值(1-5)。
-
动作(Action):状态转换时执行的操作。如清缓存、发通知、开始计时等。
-
转移(Transition):定义状态如何响应事件而改变。通常表示为"当前状态 + 事件 → 新状态"。
1.2 状态机与旗标编程对比
传统旗标式编程(Flag Hell)使用大量布尔变量控制流程,存在严重问题:
csharp复制// 典型的旗标式代码 - 难以维护
m_VFStartFlag[ws.Id] = true;
m_VFCoolStartFlag[ws.Id] = true;
m_VCEStartFlag[ws.Id] = true;
m_VFStopFlag[ws.Id] = true;
这种方式的缺陷包括:
- 状态组合爆炸(n个布尔变量产生2^n种组合)
- 修改逻辑需要追踪多个位置
- 难以理解和测试
- 容易产生竞态条件
相比之下,状态机方案:
- 明确有限的状态集合
- 单一状态变量
- 集中式状态转换逻辑
- 自文档化的设计
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. TVJ测试状态机设计
2.1 状态流转图
TVJ测试的核心状态流转如下:
code复制 marker=4 (加热结束)
Idle ───────────────────► VfCooling ◄─────────────────┐
^ │ │
│ ▼ │
│ 采集Vf数据 │
│ 实时PreTVJ │
│ │ │
│ ▼ │
│ 缓存满 + 计算Tvj │
│ │ │
│ marker=1 (下次加热开始) │
└────────────────────── CycleCompleted ───────────┘
│
▼
发完整Tvj波形
回 Idle
2.2 状态机实现方案
方案1:枚举+switch(推荐入门方案)
csharp复制private enum TvjPhase
{
Idle,
VceHeating,
VfCooling,
WaitingNextCycle
}
private readonly ConcurrentDictionary<string, TvjPhase> _phaseMap = new();
private readonly ConcurrentDictionary<string, TvjContext> _ctxMap = new();
private void ProcessMarker(WorkStation ws, double value, int marker)
{
var phase = _phaseMap.GetOrAdd(ws.Id, TvjPhase.Idle);
var ctx = _ctxMap.GetOrAdd(ws.Id, _ => new TvjContext());
switch (phase)
{
case TvjPhase.Idle:
if (marker == 4) EnterVfCooling(ws, ctx, value);
break;
case TvjPhase.VfCooling:
if (marker == 5) CollectVfPoint(ctx, value);
if (marker == 1) CompleteCycleAndBackToIdle(ws, ctx);
break;
case TvjPhase.WaitingNextCycle:
if (marker == 4) EnterVfCooling(ws, ctx, value);
break;
}
}
方案2:状态模式(企业级方案)
csharp复制abstract class TvjState
{
public virtual void OnMarker4(WorkStation ws, TvjContext ctx, double v) { }
public virtual void OnMarker5(WorkStation ws, TvjContext ctx, double v) { }
public virtual void OnMarker1(WorkStation ws, TvjContext ctx, double v) { }
}
class IdleS
