From 22c1d08dc33010b10f38e42bd15104164f3461de Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Sun, 15 Feb 2026 20:45:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(state):=20=E5=AE=9E=E7=8E=B0=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E7=8A=B6=E6=80=81=E5=9F=BA=E7=B1=BB=E7=9A=84=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E6=96=B9=E6=B3=95=E9=99=90=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为 AsyncContextAwareStateBase 添加同步方法异常抛出机制 - 禁止在异步状态中使用 OnEnter、OnExit 和 CanTransitionTo 同步方法 - 提供清晰的错误提示引导使用对应的异步方法 - 修复 StateMachine 中的状态转换逻辑确保线程安全 - 更新 IAsyncState 接口继承 IState 接口统一状态管理 --- .../state/IAsyncState.cs | 2 +- .../state/AsyncContextAwareStateBase.cs | 33 +++++++++++++++++++ GFramework.Core/state/StateMachine.cs | 9 +++-- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/GFramework.Core.Abstractions/state/IAsyncState.cs b/GFramework.Core.Abstractions/state/IAsyncState.cs index 729b8ae..517642b 100644 --- a/GFramework.Core.Abstractions/state/IAsyncState.cs +++ b/GFramework.Core.Abstractions/state/IAsyncState.cs @@ -16,7 +16,7 @@ namespace GFramework.Core.Abstractions.state; /// /// 异步状态机状态接口,定义了状态的异步行为和转换规则 /// -public interface IAsyncState +public interface IAsyncState : IState { /// /// 当状态被激活进入时异步调用 diff --git a/GFramework.Core/state/AsyncContextAwareStateBase.cs b/GFramework.Core/state/AsyncContextAwareStateBase.cs index 266a610..368641e 100644 --- a/GFramework.Core/state/AsyncContextAwareStateBase.cs +++ b/GFramework.Core/state/AsyncContextAwareStateBase.cs @@ -61,6 +61,39 @@ public class AsyncContextAwareStateBase : IAsyncState, IContextAware, IDisposabl return Task.FromResult(true); } + /// + /// 同步进入状态(不推荐使用) + /// 异步状态应该使用 OnEnterAsync 方法 + /// + /// 异步状态不支持同步操作 + public virtual void OnEnter(IState? from) + { + throw new NotSupportedException( + $"This is an async state ({GetType().Name}). Use OnEnterAsync instead of OnEnter."); + } + + /// + /// 同步退出状态(不推荐使用) + /// 异步状态应该使用 OnExitAsync 方法 + /// + /// 异步状态不支持同步操作 + public virtual void OnExit(IState? to) + { + throw new NotSupportedException( + $"This is an async state ({GetType().Name}). Use OnExitAsync instead of OnExit."); + } + + /// + /// 同步判断是否可以转换(不推荐使用) + /// 异步状态应该使用 CanTransitionToAsync 方法 + /// + /// 异步状态不支持同步操作 + public virtual bool CanTransitionTo(IState target) + { + throw new NotSupportedException( + $"This is an async state ({GetType().Name}). Use CanTransitionToAsync instead of CanTransitionTo."); + } + /// /// 设置架构上下文 /// diff --git a/GFramework.Core/state/StateMachine.cs b/GFramework.Core/state/StateMachine.cs index 70f4495..4ffd820 100644 --- a/GFramework.Core/state/StateMachine.cs +++ b/GFramework.Core/state/StateMachine.cs @@ -138,20 +138,23 @@ public class StateMachine(int maxHistorySize = 10) : IStateMachine public async Task ChangeToAsync() where T : IState { IState target; + IState? currentSnapshot; lock (_lock) { if (!States.TryGetValue(typeof(T), out target!)) throw new InvalidOperationException($"State {typeof(T).Name} not registered."); + + currentSnapshot = Current; // 在锁内获取当前状态的快照 } // 验证转换(在锁外执行异步操作) - if (Current != null) + if (currentSnapshot != null) { - var canTransition = await CanTransitionToAsync(Current, target); + var canTransition = await CanTransitionToAsync(currentSnapshot, target); if (!canTransition) { - await OnTransitionRejectedAsync(Current, target); + await OnTransitionRejectedAsync(currentSnapshot, target); return false; } }