diff --git a/GFramework.Core.Tests/coroutine/WaitForAllCoroutinesTests.cs b/GFramework.Core.Tests/coroutine/WaitForAllCoroutinesTests.cs index 35f8028..b3ae4d6 100644 --- a/GFramework.Core.Tests/coroutine/WaitForAllCoroutinesTests.cs +++ b/GFramework.Core.Tests/coroutine/WaitForAllCoroutinesTests.cs @@ -36,7 +36,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine2) }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); Assert.That(wait.IsDone, Is.False); } @@ -58,7 +58,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine2) }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); scheduler.Update(); scheduler.Update(); @@ -87,7 +87,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine3) }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); Assert.That(wait.IsDone, Is.False); Assert.That(executionCount, Is.EqualTo(0)); @@ -108,7 +108,7 @@ public class WaitForAllCoroutinesTests var scheduler = new CoroutineScheduler(timeSource); var handles = Array.Empty(); - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); Assert.That(wait.IsDone, Is.True); } @@ -119,7 +119,21 @@ public class WaitForAllCoroutinesTests [Test] public void WaitForAllCoroutines_Should_Throw_ArgumentNullException_When_Handles_Is_Null() { - Assert.Throws(() => new WaitForAllCoroutines(null!)); + var timeSource = new TestTimeSource(); + var scheduler = new CoroutineScheduler(timeSource); + + Assert.Throws(() => new WaitForAllCoroutines(scheduler, null!)); + } + + /// + /// 验证WaitForAllCoroutines应该抛出ArgumentNullException当scheduler为null + /// + [Test] + public void WaitForAllCoroutines_Should_Throw_ArgumentNullException_When_Scheduler_Is_Null() + { + var handles = Array.Empty(); + + Assert.Throws(() => new WaitForAllCoroutines(null!, handles)); } /// @@ -134,7 +148,7 @@ public class WaitForAllCoroutinesTests var handles = new List { scheduler.Run(coroutine) }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); scheduler.Update(); @@ -162,7 +176,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine3) }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); scheduler.Update(); @@ -188,7 +202,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine2) }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); Assert.That(wait.IsDone, Is.False); @@ -220,7 +234,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine2) }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); scheduler.Pause(handles[0]); @@ -248,7 +262,7 @@ public class WaitForAllCoroutinesTests var coroutine = CreateDelayedCoroutine(() => { }, 1.0); var handles = new List { scheduler.Run(coroutine) }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); wait.Update(0.1); Assert.That(wait.IsDone, Is.False); @@ -268,7 +282,7 @@ public class WaitForAllCoroutinesTests var handles = new List { default }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); Assert.That(wait.IsDone, Is.True); } @@ -289,7 +303,7 @@ public class WaitForAllCoroutinesTests default }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); scheduler.Update(); @@ -309,7 +323,7 @@ public class WaitForAllCoroutinesTests var handles = new List(); for (var i = 0; i < 20; i++) handles.Add(scheduler.Run(CreateDelayedCoroutine(() => executionCount++, 1.0))); - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); Assert.That(wait.IsDone, Is.False); @@ -339,7 +353,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine3) }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); scheduler.Update(); @@ -386,7 +400,7 @@ public class WaitForAllCoroutinesTests var scheduler = new CoroutineScheduler(timeSource); var handles = Array.Empty(); - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); Assert.That(wait, Is.InstanceOf()); } @@ -412,7 +426,7 @@ public class WaitForAllCoroutinesTests scheduler.Update(); scheduler.Update(); - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); Assert.That(wait.IsDone, Is.True); } @@ -430,7 +444,7 @@ public class WaitForAllCoroutinesTests var handle = scheduler.Run(coroutine); var handles = new List { handle, handle }; - var wait = new WaitForAllCoroutines(handles); + var wait = new WaitForAllCoroutines(scheduler, handles); for (var i = 0; i < 12; i++) scheduler.Update(); @@ -445,15 +459,6 @@ public class WaitForAllCoroutinesTests yield break; } - /// - /// 创建带回调的协程 - /// - private IEnumerator CreateCoroutineWithCallback(int id, Action callback) - { - yield return new WaitOneFrame(); - callback(); - } - /// /// 创建延迟协程 /// diff --git a/GFramework.Core/coroutine/CoroutineScheduler.cs b/GFramework.Core/coroutine/CoroutineScheduler.cs index 9e5bedc..41c3a58 100644 --- a/GFramework.Core/coroutine/CoroutineScheduler.cs +++ b/GFramework.Core/coroutine/CoroutineScheduler.cs @@ -173,25 +173,6 @@ public sealed class CoroutineScheduler( 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; @@ -373,9 +354,6 @@ public sealed class CoroutineScheduler( 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 3dc564a..24d232e 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(handles); + yield return new WaitForAllCoroutines(scheduler, handles); } /// diff --git a/GFramework.Core/coroutine/instructions/WaitForAllCoroutines.cs b/GFramework.Core/coroutine/instructions/WaitForAllCoroutines.cs index 16ad295..15e03d6 100644 --- a/GFramework.Core/coroutine/instructions/WaitForAllCoroutines.cs +++ b/GFramework.Core/coroutine/instructions/WaitForAllCoroutines.cs @@ -5,51 +5,37 @@ namespace GFramework.Core.coroutine.instructions; /// /// 等待所有协程完成的等待指令 /// -public sealed class WaitForAllCoroutines : IYieldInstruction +/// 协程调度器,用于检查协程是否存活 +/// 协程句柄列表,用于跟踪需要等待的协程 +public sealed class WaitForAllCoroutines( + CoroutineScheduler scheduler, + IReadOnlyList handles) + : IYieldInstruction { - private readonly HashSet _pendingHandles; - private bool _isDone; + private readonly IReadOnlyList _handles = + handles ?? throw new ArgumentNullException(nameof(handles)); + + private readonly CoroutineScheduler _scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler)); /// - /// 初始化 WaitForAllCoroutines 类的新实例 + /// 更新方法,在每一帧调用 /// - /// 要等待完成的协程句柄列表 - public WaitForAllCoroutines(IReadOnlyList handles) - { - ArgumentNullException.ThrowIfNull(handles); - - _pendingHandles = new HashSet(handles); - _isDone = _pendingHandles.Count == 0; - } - - /// - /// 获取所有待完成的协程句柄 - /// - internal IReadOnlyCollection PendingHandles => _pendingHandles; - - /// - /// 更新方法 - 由调度器调用 - /// - /// 时间增量 + /// 自上一帧以来的时间间隔 public void Update(double deltaTime) { - // 不需要做任何事,由调度器通知完成 + // 不需要做任何事 } /// - /// 获取一个值,指示是否所有协程都已完成 + /// 获取一个值,指示所有协程是否已完成执行 /// - public bool IsDone => _isDone; - - /// - /// 通知某个协程已完成 - /// - /// 已完成的协程句柄 - internal void NotifyCoroutineComplete(CoroutineHandle handle) + /// 当所有协程都已完成时返回true,否则返回false + public bool IsDone { - // 从待处理句柄集合中移除已完成的协程句柄 - _pendingHandles.Remove(handle); - if (_pendingHandles.Count == 0) - _isDone = true; + get + { + // 检查所有协程句柄是否都不在调度器中存活 + return _handles.All(handle => !_scheduler.IsCoroutineAlive(handle)); + } } } \ No newline at end of file