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