refactor(coroutine): 重构协程调度器以支持WaitForCoroutine指令

- 将WaitForCoroutine改为构造函数注入协程枚举器的方式
- 添加ProcessWaitingInstruction方法专门处理等待指令
- 添加IsWaiting方法判断协程等待状态
- 添加ProcessCoroutineStep方法处理协程步骤推进
- 添加HandleYieldInstruction方法处理yield指令逻辑
- 实现WaitForCoroutine指令的完整协程等待功能
- 在协程完成时通知WaitForCoroutine指令标记完成状态
- 优化协程调度器的执行流程和异常处理机制
This commit is contained in:
GeWuYou 2026-02-01 15:11:51 +08:00
parent 4943fc5c70
commit 120fd14cd8
2 changed files with 87 additions and 21 deletions

View File

@ -1,4 +1,5 @@
using GFramework.Core.Abstractions.coroutine;
using GFramework.Core.coroutine.instructions;
namespace GFramework.Core.coroutine;
@ -98,21 +99,12 @@ public sealed class CoroutineScheduler(
try
{
// 1⃣ 处理等待指令
if (slot.Waiting != null)
ProcessWaitingInstruction(slot, delta);
if (!IsWaiting(slot))
{
slot.Waiting.Update(delta);
if (!slot.Waiting.IsDone)
continue;
slot.Waiting = null;
ProcessCoroutineStep(slot, i);
}
// 2⃣ 推进协程
if (!slot.Enumerator.MoveNext())
Complete(i);
else
slot.Waiting = slot.Enumerator.Current;
}
catch (Exception ex)
{
@ -121,6 +113,68 @@ public sealed class CoroutineScheduler(
}
}
/// <summary>
/// 处理协程的等待指令
/// </summary>
/// <param name="slot">协程槽位</param>
/// <param name="delta">时间差值</param>
private static void ProcessWaitingInstruction(CoroutineSlot slot, double delta)
{
if (slot.Waiting == null)
return;
slot.Waiting.Update(delta);
if (slot.Waiting.IsDone)
slot.Waiting = null;
}
/// <summary>
/// 判断协程是否正在等待
/// </summary>
/// <param name="slot">协程槽位</param>
/// <returns>是否正在等待</returns>
private static bool IsWaiting(CoroutineSlot slot)
{
return slot.Waiting != null && !slot.Waiting.IsDone;
}
/// <summary>
/// 处理协程步骤推进
/// </summary>
/// <param name="slot">协程槽位</param>
/// <param name="slotIndex">槽位索引</param>
private void ProcessCoroutineStep(CoroutineSlot slot, int slotIndex)
{
if (!slot.Enumerator.MoveNext())
{
Complete(slotIndex);
return;
}
var current = slot.Enumerator.Current;
HandleYieldInstruction(slot, current);
}
/// <summary>
/// 处理协程的yield指令
/// </summary>
/// <param name="slot">协程槽位</param>
/// <param name="instruction">yield指令</param>
private void HandleYieldInstruction(CoroutineSlot slot, IYieldInstruction instruction)
{
// 处理 WaitForCoroutine 指令
if (instruction is WaitForCoroutine waitForCoroutine)
{
// 启动被等待的协程并建立等待关系
var targetHandle = Run(waitForCoroutine.Coroutine);
WaitForCoroutine(slot.Handle, targetHandle);
}
else
{
slot.Waiting = instruction;
}
}
#endregion
#region Pause / Resume / Kill
@ -300,6 +354,12 @@ public sealed class CoroutineScheduler(
if (!_metadata.TryGetValue(waiter, out var meta)) continue;
var s = _slots[meta.SlotIndex];
if (s == null) continue;
// 通知 WaitForCoroutine 指令协程已完成
if (s.Waiting is WaitForCoroutine wfc)
{
wfc.Complete();
}
s.State = CoroutineState.Running;
meta.State = CoroutineState.Running;
}

View File

@ -5,10 +5,21 @@ namespace GFramework.Core.coroutine.instructions;
/// <summary>
/// 等待协程完成的指令类实现IYieldInstruction接口
/// </summary>
public sealed class WaitForCoroutine : IYieldInstruction
/// <param name="coroutine">需要等待完成的协程枚举器</param>
public sealed class WaitForCoroutine(IEnumerator<IYieldInstruction> coroutine) : IYieldInstruction
{
/// <summary>
/// 更新方法,用于处理时间更新逻辑
/// 获取内部协程枚举器
/// </summary>
internal IEnumerator<IYieldInstruction> Coroutine => coroutine;
/// <summary>
/// 获取当前等待的协程是否已完成
/// </summary>
public bool IsDone { get; private set; }
/// <summary>
/// 更新方法,用于处理协程等待逻辑
/// </summary>
/// <param name="delta">时间增量</param>
public void Update(double delta)
@ -16,12 +27,7 @@ public sealed class WaitForCoroutine : IYieldInstruction
}
/// <summary>
/// 获取协程是否已完成的状态
/// </summary>
public bool IsDone { get; private set; }
/// <summary>
/// 内部方法,用于标记协程完成状态
/// 标记协程等待完成
/// </summary>
internal void Complete()
{