Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions GameFrameX.Core/Actors/Actor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,34 @@ public async Task<IComponentAgent> GetComponentAgentAsync(Type agentType, bool i
}

var agent = component.GetAgent(agentType);
if (!component.IsActive)
// 快速路径:只有整个激活流程结束才放行——IsActive 在激活一开始即置位,
// 激活进行中(读库/代理三段回调未完)时外部调用者必须排队等待,不能提前拿到 agent。
if (!component.IsActivationCompleted)
{
await SendAsyncWithoutCheck(() => ActivateComponentAsync(component, agent, compType));
await SendAsyncWithoutCheck(() => ActivateComponentIfNeededAsync(component, agent, compType));
}

return agent;
}

/// <summary>
/// 在 actor 上下文内复检后再激活:排在前面的激活工作单元已完成(或当前是激活过程中的内联嵌套调用,
/// IsActive 已为 true)时直接返回,不重复执行激活逻辑。
/// </summary>
/// <param name="component">要激活的组件实例</param>
/// <param name="agent">组件对应的代理实例</param>
/// <param name="compType">组件类型,用于日志记录</param>
/// <returns>表示异步操作的任务</returns>
private Task ActivateComponentIfNeededAsync(BaseComponent component, IComponentAgent agent, Type compType)
{
if (component.IsActive)
{
return Task.CompletedTask;
}

return ActivateComponentAsync(component, agent, compType);
}

/// <summary>
/// 激活指定组件并依次调用其代理的激活生命周期方法
/// </summary>
Expand Down Expand Up @@ -213,6 +233,8 @@ private async Task ActivateComponentAsync(BaseComponent component, IComponentAge
throw;
}
}
// 与既有行为一致:激活失败也视为流程结束(不重试),等待方不再被阻塞。
component.IsActivationCompleted = true;
}

/// <summary>
Expand Down
22 changes: 22 additions & 0 deletions GameFrameX.Core/Components/BaseComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@ internal long ActorId
/// </summary>
public bool IsActive { get; private set; }

/// <summary>
/// 激活流程(组件激活 + 代理三段激活回调)是否已全部完成。
/// </summary>
/// <remarks>
/// 由 actor 上下文写入,可能被 actor 外部线程读取,因此使用 volatile;
/// 与 <see cref="IsActive"/>(激活开始即置位)区分,供快速路径判断是否可以放行。
/// Whether the whole activation flow (component activation plus the agent's three-phase
/// activation callbacks) has completed; written on the actor context and read from outside,
/// hence volatile. Distinct from <see cref="IsActive"/> (set at activation start).
/// </remarks>
private volatile bool _isActivationCompleted;

/// <summary>
/// 激活流程是否已全部完成
/// </summary>
internal bool IsActivationCompleted
{
get { return _isActivationCompleted; }
set { _isActivationCompleted = value; }
}

/// <summary>
/// 是否准备完毕
/// </summary>
Expand Down Expand Up @@ -136,6 +157,7 @@ public virtual async Task InactiveAsync()
finally
{
IsActive = false;
_isActivationCompleted = false;
}
}

Expand Down
Loading