cefsharp/CefSharp · error · ArgumentOutOfRangeException

maxDegreeOfParallelism

Error message

maxDegreeOfParallelism

What it means

Thrown by the LimitedConcurrencyLevelTaskScheduler constructor when maxDegreeOfParallelism is less than 1. The scheduler enforces an upper bound on concurrent task execution and a bound of zero or negative is meaningless, so it rejects it immediately with ArgumentOutOfRangeException.

Source

Thrown at CefSharp/Internals/Tasks/LimitedConcurrencyLevelTaskScheduler.cs:42

        [ThreadStatic]
        private static bool _currentThreadIsProcessingItems;
        /// <summary>The list of tasks to be executed.</summary>
        private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); // protected by lock(_tasks)
        /// <summary>The maximum concurrency level allowed by this scheduler.</summary>
        private readonly int _maxDegreeOfParallelism;
        /// <summary>Whether the scheduler is currently processing work items.</summary>
        private int _delegatesQueuedOrRunning = 0; // protected by lock(_tasks)

        /// <summary>
        /// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the
        /// specified degree of parallelism.
        /// </summary>
        /// <param name="maxDegreeOfParallelism">The maximum degree of parallelism provided by this scheduler.</param>
        public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
        {
            if (maxDegreeOfParallelism < 1)
            {
                throw new ArgumentOutOfRangeException("maxDegreeOfParallelism");
            }

            _maxDegreeOfParallelism = maxDegreeOfParallelism;
        }

        /// <summary>Queues a task to the scheduler.</summary>
        /// <param name="task">The task to be queued.</param>
        protected sealed override void QueueTask(Task task)
        {
            // Add the task to the list of tasks to be processed.  If there aren't enough
            // delegates currently queued or running to process tasks, schedule another.
            lock (_tasks)
            {
                _tasks.AddLast(task);
                if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism)
                {
                    ++_delegatesQueuedOrRunning;
                    NotifyThreadPoolOfPendingWork();

View on GitHub (pinned to 16bc6e0711)

Solutions

  1. Pass a value >= 1 (commonly Environment.ProcessorCount or a fixed sane default).
  2. Clamp the computed value: Math.Max(1, configured) before constructing.
  3. Validate configuration at startup so a bad value fails early with a clear message.
  4. Unit-test the scheduler construction path with boundary inputs.

Example fix

// before
var sched = new LimitedConcurrencyLevelTaskScheduler(configuredDegree); // 0 -> throws

// after
var degree = Math.Max(1, configuredDegree);
var sched = new LimitedConcurrencyLevelTaskScheduler(degree);
Defensive patterns

Strategy: validation

Validate before calling

var degree = Math.Max(1, configuredDegree);
var scheduler = new LimitedConcurrencyLevelTaskScheduler(degree);

Try / catch

try { var s = new LimitedConcurrencyLevelTaskScheduler(n); }
catch (ArgumentOutOfRangeException) { var s = new LimitedConcurrencyLevelTaskScheduler(1); }

Prevention

When it happens

Trigger: Constructing new LimitedConcurrencyLevelTaskScheduler(0) or a negative value; computing the degree from configuration/Environment.ProcessorCount and getting 0 (e.g. on a constrained host or a config typo).

Common situations: Config-driven parallelism defaulting to 0; subtracting from ProcessorCount and going negative; shared scheduler factory misconfigured.

Related errors


AI-assisted analysis of cefsharp/CefSharp@16bc6e0711 (2026-08-13). Data as JSON: /api/errors/e078286ca190e300. Report an issue: GitHub.