using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace PCL.Core.Utils.Threading; // Partly generated by o4-mini-high (20250709) /// /// 允许限制最大并发度的 TaskScheduler /// public sealed class LimitedConcurrencyLevelTaskScheduler : TaskScheduler { [ThreadStatic] private static bool _currentThreadIsProcessingItems; private readonly LinkedList _tasks = []; private int _delegatesQueuedOrRunning = 0; private readonly int _maxDegreeOfParallelism; public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism) { if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException(nameof(maxDegreeOfParallelism)); _maxDegreeOfParallelism = maxDegreeOfParallelism; } public override int MaximumConcurrencyLevel => _maxDegreeOfParallelism; protected override IEnumerable GetScheduledTasks() { var lockTaken = false; try { Monitor.TryEnter(_tasks, ref lockTaken); if (lockTaken) return _tasks.ToArray(); else throw new NotSupportedException(); } finally { if (lockTaken) Monitor.Exit(_tasks); } } protected override void QueueTask(Task task) { lock (_tasks) { _tasks.AddLast(task); if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism) { _delegatesQueuedOrRunning++; ThreadPool.UnsafeQueueUserWorkItem(_ => _ProcessTasks(), null); } } } private void _ProcessTasks() { _currentThreadIsProcessingItems = true; try { while (true) { Task item; lock (_tasks) { if (_tasks.Count == 0) { _delegatesQueuedOrRunning--; break; } item = _tasks.First!.Value; _tasks.RemoveFirst(); } TryExecuteTask(item); } } finally { _currentThreadIsProcessingItems = false; } } protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) { if (!_currentThreadIsProcessingItems) return false; if (taskWasPreviouslyQueued) { return TryDequeue(task) && TryExecuteTask(task); } else { return TryExecuteTask(task); } } protected override bool TryDequeue(Task task) { lock (_tasks) { return _tasks.Remove(task); } } }