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;
}
}