From 74f27ddfd535971200d6f99e818cfc3f0dedf6b0 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Fri, 6 Mar 2026 12:59:05 +0800 Subject: [PATCH] =?UTF-8?q?refactor(coroutine):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=8D=8F=E7=A8=8B=E8=B0=83=E5=BA=A6=E5=99=A8=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E6=9A=82=E5=81=9C=E8=AE=A1=E6=95=B0=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 _pausedCount 字段直接跟踪暂停协程数量 - 将统计信息中的 ActiveCount 和 PausedCount 改为线程安全的原子操作 - 在暂停和恢复协程时直接更新 _pausedCount 计数 - 修复 KillGroup 方法中的并发修改异常问题 - 重置统计信息时使用原子操作清零计数字段 --- .../coroutine/CoroutineScheduler.cs | 9 +++++++-- .../coroutine/CoroutineStatistics.cs | 18 ++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/GFramework.Core/coroutine/CoroutineScheduler.cs b/GFramework.Core/coroutine/CoroutineScheduler.cs index 698e8e3..8c20f38 100644 --- a/GFramework.Core/coroutine/CoroutineScheduler.cs +++ b/GFramework.Core/coroutine/CoroutineScheduler.cs @@ -27,6 +27,7 @@ public sealed class CoroutineScheduler( private readonly ITimeSource _timeSource = timeSource ?? throw new ArgumentNullException(nameof(timeSource)); private readonly Dictionary> _waiting = new(); private int _nextSlot; + private int _pausedCount; private CoroutineSlot?[] _slots = new CoroutineSlot?[initialCapacity]; @@ -133,7 +134,7 @@ public sealed class CoroutineScheduler( if (_statistics != null) { _statistics.ActiveCount = ActiveCoroutineCount; - _statistics.PausedCount = _metadata.Count(m => m.Value.State == CoroutineState.Paused); + _statistics.PausedCount = _pausedCount; } // 按优先级排序槽位索引(高优先级优先执行) @@ -264,6 +265,7 @@ public sealed class CoroutineScheduler( slot.State = CoroutineState.Paused; meta.State = CoroutineState.Paused; + _pausedCount++; return true; } @@ -283,6 +285,7 @@ public sealed class CoroutineScheduler( slot.State = CoroutineState.Running; meta.State = CoroutineState.Running; + _pausedCount--; return true; } @@ -340,7 +343,8 @@ public sealed class CoroutineScheduler( if (!_grouped.TryGetValue(group, out var handles)) return 0; - return handles.Count(Kill); + var copy = handles.ToArray(); + return copy.Count(Kill); } /// @@ -409,6 +413,7 @@ public sealed class CoroutineScheduler( _nextSlot = 0; ActiveCoroutineCount = 0; + _pausedCount = 0; return count; } diff --git a/GFramework.Core/coroutine/CoroutineStatistics.cs b/GFramework.Core/coroutine/CoroutineStatistics.cs index 1807283..428b7f9 100644 --- a/GFramework.Core/coroutine/CoroutineStatistics.cs +++ b/GFramework.Core/coroutine/CoroutineStatistics.cs @@ -12,7 +12,9 @@ internal sealed class CoroutineStatistics : ICoroutineStatistics private readonly Dictionary _countByPriority = new(); private readonly Dictionary _countByTag = new(); private readonly object _lock = new(); + private int _activeCount; private double _maxExecutionTimeMs; + private int _pausedCount; private long _totalCompleted; private long _totalExecutionTimeMs; private long _totalFailed; @@ -28,10 +30,18 @@ internal sealed class CoroutineStatistics : ICoroutineStatistics public long TotalFailed => Interlocked.Read(ref _totalFailed); /// - public int ActiveCount { get; set; } + public int ActiveCount + { + get => Interlocked.CompareExchange(ref _activeCount, 0, 0); + set => Interlocked.Exchange(ref _activeCount, value); + } /// - public int PausedCount { get; set; } + public int PausedCount + { + get => Interlocked.CompareExchange(ref _pausedCount, 0, 0); + set => Interlocked.Exchange(ref _pausedCount, value); + } /// public double AverageExecutionTimeMs @@ -84,14 +94,14 @@ internal sealed class CoroutineStatistics : ICoroutineStatistics Interlocked.Exchange(ref _totalCompleted, 0); Interlocked.Exchange(ref _totalFailed, 0); Interlocked.Exchange(ref _totalExecutionTimeMs, 0); + Interlocked.Exchange(ref _activeCount, 0); + Interlocked.Exchange(ref _pausedCount, 0); lock (_lock) { _maxExecutionTimeMs = 0; _countByPriority.Clear(); _countByTag.Clear(); - ActiveCount = 0; - PausedCount = 0; } }