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; } }