mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
refactor(coroutine): 重构 WaitForAllCoroutines 实现
- 修改 WaitForAllCoroutines 构造函数,添加 CoroutineScheduler 参数 - 移除 WaitForAllCoroutines 内部的待处理句柄集合和完成状态管理 - 修改 WaitForAllCoroutines 的 IsDone 属性实现,改为通过调度器检查协程状态 - 移除 WaitForAllCoroutines 的 NotifyCoroutineComplete 方法 - 更新 CoroutineScheduler 中对 WaitForAllCoroutines 的处理逻辑 - 移除调度器中的协程完成通知相关代码 - 更新所有相关测试用例以适应新的构造函数参数 - 添加对 scheduler 参数的空值验证测试 - [release ci]
This commit is contained in:
parent
65fdea6c12
commit
7242f58029
@ -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<CoroutineHandle>();
|
||||
|
||||
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<ArgumentNullException>(() => new WaitForAllCoroutines(null!));
|
||||
var timeSource = new TestTimeSource();
|
||||
var scheduler = new CoroutineScheduler(timeSource);
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => new WaitForAllCoroutines(scheduler, null!));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证WaitForAllCoroutines应该抛出ArgumentNullException当scheduler为null
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitForAllCoroutines_Should_Throw_ArgumentNullException_When_Scheduler_Is_Null()
|
||||
{
|
||||
var handles = Array.Empty<CoroutineHandle>();
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => new WaitForAllCoroutines(null!, handles));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -134,7 +148,7 @@ public class WaitForAllCoroutinesTests
|
||||
|
||||
var handles = new List<CoroutineHandle> { 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<CoroutineHandle> { 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<CoroutineHandle> { 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<CoroutineHandle>();
|
||||
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<CoroutineHandle>();
|
||||
|
||||
var wait = new WaitForAllCoroutines(handles);
|
||||
var wait = new WaitForAllCoroutines(scheduler, handles);
|
||||
|
||||
Assert.That(wait, Is.InstanceOf<IYieldInstruction>());
|
||||
}
|
||||
@ -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<CoroutineHandle> { 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建带回调的协程
|
||||
/// </summary>
|
||||
private IEnumerator<IYieldInstruction> CreateCoroutineWithCallback(int id, Action callback)
|
||||
{
|
||||
yield return new WaitOneFrame();
|
||||
callback();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建延迟协程
|
||||
/// </summary>
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -86,7 +86,7 @@ public static class CoroutineExtensions
|
||||
}
|
||||
|
||||
// 等待所有协程完成
|
||||
yield return new WaitForAllCoroutines(handles);
|
||||
yield return new WaitForAllCoroutines(scheduler, handles);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -5,51 +5,37 @@ namespace GFramework.Core.coroutine.instructions;
|
||||
/// <summary>
|
||||
/// 等待所有协程完成的等待指令
|
||||
/// </summary>
|
||||
public sealed class WaitForAllCoroutines : IYieldInstruction
|
||||
/// <param name="scheduler">协程调度器,用于检查协程是否存活</param>
|
||||
/// <param name="handles">协程句柄列表,用于跟踪需要等待的协程</param>
|
||||
public sealed class WaitForAllCoroutines(
|
||||
CoroutineScheduler scheduler,
|
||||
IReadOnlyList<CoroutineHandle> handles)
|
||||
: IYieldInstruction
|
||||
{
|
||||
private readonly HashSet<CoroutineHandle> _pendingHandles;
|
||||
private bool _isDone;
|
||||
private readonly IReadOnlyList<CoroutineHandle> _handles =
|
||||
handles ?? throw new ArgumentNullException(nameof(handles));
|
||||
|
||||
private readonly CoroutineScheduler _scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler));
|
||||
|
||||
/// <summary>
|
||||
/// 初始化 WaitForAllCoroutines 类的新实例
|
||||
/// 更新方法,在每一帧调用
|
||||
/// </summary>
|
||||
/// <param name="handles">要等待完成的协程句柄列表</param>
|
||||
public WaitForAllCoroutines(IReadOnlyList<CoroutineHandle> handles)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(handles);
|
||||
|
||||
_pendingHandles = new HashSet<CoroutineHandle>(handles);
|
||||
_isDone = _pendingHandles.Count == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有待完成的协程句柄
|
||||
/// </summary>
|
||||
internal IReadOnlyCollection<CoroutineHandle> PendingHandles => _pendingHandles;
|
||||
|
||||
/// <summary>
|
||||
/// 更新方法 - 由调度器调用
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间增量</param>
|
||||
/// <param name="deltaTime">自上一帧以来的时间间隔</param>
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
// 不需要做任何事,由调度器通知完成
|
||||
// 不需要做任何事
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,指示是否所有协程都已完成
|
||||
/// 获取一个值,指示所有协程是否已完成执行
|
||||
/// </summary>
|
||||
public bool IsDone => _isDone;
|
||||
|
||||
/// <summary>
|
||||
/// 通知某个协程已完成
|
||||
/// </summary>
|
||||
/// <param name="handle">已完成的协程句柄</param>
|
||||
internal void NotifyCoroutineComplete(CoroutineHandle handle)
|
||||
/// <returns>当所有协程都已完成时返回true,否则返回false</returns>
|
||||
public bool IsDone
|
||||
{
|
||||
// 从待处理句柄集合中移除已完成的协程句柄
|
||||
_pendingHandles.Remove(handle);
|
||||
if (_pendingHandles.Count == 0)
|
||||
_isDone = true;
|
||||
get
|
||||
{
|
||||
// 检查所有协程句柄是否都不在调度器中存活
|
||||
return _handles.All(handle => !_scheduler.IsCoroutineAlive(handle));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user