GFramework/GFramework.Game/coroutine/CoroutineHandle.cs
GeWuYou f143cf5c1b feat(coroutine): 实现协程系统核心功能
- 添加协程上下文、句柄、调度器和作用域管理类
- 实现协程等待指令包括 WaitForSeconds、WaitUntil 和 WaitWhile
- 创建协程系统和全局协程作用域管理器
- 定义协程相关抽象接口 ICoroutineScheduler、ICoroutineScope 等
- 升级 Meziantou.Analyzer 依赖版本至 2.0.283
- 升级 Meziantou.Polyfill 依赖版本至 1.0.100
2026-01-20 23:05:15 +08:00

118 lines
2.9 KiB
C#

using System.Collections;
using GFramework.Game.Abstractions.coroutine;
namespace GFramework.Game.coroutine;
public class CoroutineHandle : IYieldInstruction
{
private readonly Stack<IEnumerator> _stack = new();
private IYieldInstruction? _waitingInstruction;
internal CoroutineHandle(IEnumerator routine, CoroutineContext context, IYieldInstruction? waitingInstruction)
{
_stack.Push(routine);
Context = context;
_waitingInstruction = waitingInstruction;
}
public CoroutineContext Context { get; }
public bool IsCancelled { get; private set; }
public bool IsDone { get; private set; }
void IYieldInstruction.Update(float deltaTime)
{
InternalUpdate(deltaTime);
}
public event Action? OnComplete;
public event Action<Exception>? OnError;
private bool InternalUpdate(float deltaTime)
{
if (IsDone) return false;
if (_waitingInstruction != null)
{
_waitingInstruction.Update(deltaTime);
if (!_waitingInstruction.IsDone) return true;
_waitingInstruction = null;
}
if (_stack.Count == 0)
{
Complete();
return false;
}
try
{
var current = _stack.Peek();
if (current.MoveNext())
{
ProcessYieldValue(current.Current);
return true;
}
_stack.Pop();
return _stack.Count > 0 || !CompleteCheck();
}
catch (Exception ex)
{
HandleError(ex);
return false;
}
}
private void ProcessYieldValue(object yielded)
{
switch (yielded)
{
case null:
break;
case IEnumerator nested:
_stack.Push(nested);
break;
// ✅ 将更具体的类型放在前面
case CoroutineHandle otherHandle:
_waitingInstruction = otherHandle;
break;
case IYieldInstruction instruction:
_waitingInstruction = instruction;
break;
default:
throw new InvalidOperationException($"Unsupported yield type: {yielded.GetType()}");
}
}
private bool CompleteCheck()
{
if (_stack.Count == 0) Complete();
return IsDone;
}
private void Complete()
{
if (IsDone) return;
IsDone = true;
_stack.Clear();
_waitingInstruction = null;
OnComplete?.Invoke();
}
private void HandleError(Exception ex)
{
IsDone = true;
_stack.Clear();
_waitingInstruction = null;
OnError?.Invoke(ex);
}
public void Cancel()
{
if (IsDone) return;
IsDone = true;
IsCancelled = true;
_stack.Clear();
_waitingInstruction = null;
}
}