From ae37b8c5f1b48de6a78f1f2aa1b2797cef006dfa Mon Sep 17 00:00:00 2001
From: GeWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Sun, 1 Feb 2026 15:27:49 +0800
Subject: [PATCH] =?UTF-8?q?refactor(coroutine):=20=E9=87=8D=E6=9E=84?=
=?UTF-8?q?=E5=8D=8F=E7=A8=8B=E7=AD=89=E5=BE=85=E6=9C=BA=E5=88=B6=E5=B9=B6?=
=?UTF-8?q?=E7=A7=BB=E9=99=A4Held=E7=8A=B6=E6=80=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 移除了CoroutineState中的Held状态
- WaitForAllCoroutines不再依赖CoroutineScheduler参数
- 使用HashSet替代IReadOnlyList存储待处理协程句柄
- 添加NotifyCoroutineComplete方法通知协程完成
- 修改HandleYieldInstruction方法使用switch表达式处理不同等待指令
- 移除WaitForCoroutine逻辑中对Held状态的设置
- 添加对WaitForAllCoroutines的完成通知支持
---
.../coroutine/CoroutineState.cs | 5 --
.../coroutine/CoroutineMetadata.cs | 3 +-
.../coroutine/CoroutineScheduler.cs | 62 ++++++++++++-------
.../extensions/CoroutineExtensions.cs | 2 +-
.../instructions/WaitForAllCoroutines.cs | 47 ++++++++++----
5 files changed, 76 insertions(+), 43 deletions(-)
diff --git a/GFramework.Core.Abstractions/coroutine/CoroutineState.cs b/GFramework.Core.Abstractions/coroutine/CoroutineState.cs
index e9c7c07..6eb7535 100644
--- a/GFramework.Core.Abstractions/coroutine/CoroutineState.cs
+++ b/GFramework.Core.Abstractions/coroutine/CoroutineState.cs
@@ -15,11 +15,6 @@ public enum CoroutineState
///
Paused,
- ///
- /// 协程被锁定或等待其他协程完成
- ///
- Held,
-
///
/// 协程已完成执行
///
diff --git a/GFramework.Core/coroutine/CoroutineMetadata.cs b/GFramework.Core/coroutine/CoroutineMetadata.cs
index d967d37..47e0fe4 100644
--- a/GFramework.Core/coroutine/CoroutineMetadata.cs
+++ b/GFramework.Core/coroutine/CoroutineMetadata.cs
@@ -27,6 +27,5 @@ internal class CoroutineMetadata
///
public bool IsActive =>
State is CoroutineState.Running
- or CoroutineState.Paused
- or CoroutineState.Held;
+ or CoroutineState.Paused;
}
\ No newline at end of file
diff --git a/GFramework.Core/coroutine/CoroutineScheduler.cs b/GFramework.Core/coroutine/CoroutineScheduler.cs
index 6115b05..9e5bedc 100644
--- a/GFramework.Core/coroutine/CoroutineScheduler.cs
+++ b/GFramework.Core/coroutine/CoroutineScheduler.cs
@@ -162,16 +162,39 @@ public sealed class CoroutineScheduler(
/// yield指令
private void HandleYieldInstruction(CoroutineSlot slot, IYieldInstruction instruction)
{
- // 处理 WaitForCoroutine 指令
- if (instruction is WaitForCoroutine waitForCoroutine)
+ switch (instruction)
{
- // 启动被等待的协程并建立等待关系
- var targetHandle = Run(waitForCoroutine.Coroutine);
- WaitForCoroutine(slot.Handle, targetHandle);
- }
- else
- {
- slot.Waiting = instruction;
+ // 处理 WaitForCoroutine 指令
+ case WaitForCoroutine waitForCoroutine:
+ {
+ // 启动被等待的协程并建立等待关系
+ var targetHandle = Run(waitForCoroutine.Coroutine);
+ slot.Waiting = waitForCoroutine;
+ WaitForCoroutine(slot.Handle, targetHandle);
+ break;
+ }
+ case WaitForAllCoroutines waitForAll:
+ {
+ slot.Waiting = waitForAll;
+ // 为所有待完成的协程建立等待关系
+ foreach (var handle in waitForAll.PendingHandles)
+ {
+ if (_metadata.ContainsKey(handle))
+ {
+ WaitForCoroutine(slot.Handle, handle);
+ }
+ else
+ {
+ // 协程已完成,立即通知
+ waitForAll.NotifyCoroutineComplete(handle);
+ }
+ }
+
+ break;
+ }
+ default:
+ slot.Waiting = instruction;
+ break;
}
}
@@ -250,16 +273,6 @@ public sealed class CoroutineScheduler(
if (!_metadata.ContainsKey(target))
return;
- if (_metadata.TryGetValue(current, out var meta))
- {
- var slot = _slots[meta.SlotIndex];
- if (slot != null)
- {
- slot.State = CoroutineState.Held;
- meta.State = CoroutineState.Held;
- }
- }
-
if (!_waiting.TryGetValue(target, out var set))
{
set = [];
@@ -354,10 +367,15 @@ 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)
+ switch (s.Waiting)
{
- wfc.Complete();
+ // 通知 WaitForCoroutine 指令协程已完成
+ case WaitForCoroutine wfc:
+ wfc.Complete();
+ break;
+ case WaitForAllCoroutines wfa:
+ wfa.NotifyCoroutineComplete(handle);
+ break;
}
s.State = CoroutineState.Running;
diff --git a/GFramework.Core/coroutine/extensions/CoroutineExtensions.cs b/GFramework.Core/coroutine/extensions/CoroutineExtensions.cs
index 24d232e..3dc564a 100644
--- a/GFramework.Core/coroutine/extensions/CoroutineExtensions.cs
+++ b/GFramework.Core/coroutine/extensions/CoroutineExtensions.cs
@@ -86,7 +86,7 @@ public static class CoroutineExtensions
}
// 等待所有协程完成
- yield return new WaitForAllCoroutines(scheduler, handles);
+ yield return new WaitForAllCoroutines(handles);
}
///
diff --git a/GFramework.Core/coroutine/instructions/WaitForAllCoroutines.cs b/GFramework.Core/coroutine/instructions/WaitForAllCoroutines.cs
index c0a33a8..16ad295 100644
--- a/GFramework.Core/coroutine/instructions/WaitForAllCoroutines.cs
+++ b/GFramework.Core/coroutine/instructions/WaitForAllCoroutines.cs
@@ -7,28 +7,49 @@ namespace GFramework.Core.coroutine.instructions;
///
public sealed class WaitForAllCoroutines : IYieldInstruction
{
- private readonly IReadOnlyList _handles;
- private readonly CoroutineScheduler _scheduler;
+ private readonly HashSet _pendingHandles;
private bool _isDone;
- public WaitForAllCoroutines(
- CoroutineScheduler scheduler,
- IReadOnlyList handles)
+ ///
+ /// 初始化 WaitForAllCoroutines 类的新实例
+ ///
+ /// 要等待完成的协程句柄列表
+ public WaitForAllCoroutines(IReadOnlyList handles)
{
- _scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler));
- _handles = handles ?? throw new ArgumentNullException(nameof(handles));
+ ArgumentNullException.ThrowIfNull(handles);
- // 空列表直接完成
- _isDone = _handles.Count == 0;
+ _pendingHandles = new HashSet(handles);
+ _isDone = _pendingHandles.Count == 0;
}
+ ///
+ /// 获取所有待完成的协程句柄
+ ///
+ internal IReadOnlyCollection PendingHandles => _pendingHandles;
+
+ ///
+ /// 更新方法 - 由调度器调用
+ ///
+ /// 时间增量
public void Update(double deltaTime)
{
- if (_isDone) return;
-
- // 检查所有协程是否都已完成
- _isDone = _handles.All(handle => !_scheduler.IsCoroutineAlive(handle));
+ // 不需要做任何事,由调度器通知完成
}
+ ///
+ /// 获取一个值,指示是否所有协程都已完成
+ ///
public bool IsDone => _isDone;
+
+ ///
+ /// 通知某个协程已完成
+ ///
+ /// 已完成的协程句柄
+ internal void NotifyCoroutineComplete(CoroutineHandle handle)
+ {
+ // 从待处理句柄集合中移除已完成的协程句柄
+ _pendingHandles.Remove(handle);
+ if (_pendingHandles.Count == 0)
+ _isDone = true;
+ }
}
\ No newline at end of file