stride3d/stride · error · ArgumentOutOfRangeException
maximumConcurrencyLevel
Error message
maximumConcurrencyLevel
What it means
EffectPriorityScheduler schedules shader-compile tasks on dedicated threads with a bounded concurrency level. Zero is invalid (would mean no worker threads), so the constructor throws ArgumentOutOfRangeException for maximumConcurrencyLevel == 0. Note negative values are not rejected by this guard.
Solutions
- Pass at least 1 for maximumConcurrencyLevel, or use Environment.ProcessorCount.
- Clamp the configured value before constructing: Math.Max(1, configured).
- Fix config/container settings that resolve to 0.
Example fix
// before var scheduler = new EffectPriorityScheduler(ThreadPriority.Normal, config.MaxConcurrency); // after var scheduler = new EffectPriorityScheduler(ThreadPriority.Normal, Math.Max(1, config.MaxConcurrency));
Defensive patterns
Strategy: validation
Validate before calling
if (maximumConcurrencyLevel < 1) throw new InvalidOperationException($"maximumConcurrencyLevel must be >= 1, got {maximumConcurrencyLevel}"); Type guard
null
Try / catch
try { var scheduler = new EffectPriorityScheduler(priority, level); } catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "maximumConcurrencyLevel") { level = Math.Max(1, level); } Prevention
- Clamp configured concurrency with Math.Max(1, value)
- Avoid literal 0 in scheduler configs
- Use Environment.ProcessorCount as default
When it happens
Trigger: new EffectPriorityScheduler(threadPriority, 0) — passing a zero concurrency level, e.g. from a config value of 0 or Environment.ProcessorCount miscomputation.
Common situations: Config files with maxConcurrency=0 meant as 'unlimited'; CPU-count detection returning 0 in restricted containers.
Related errors
- Expecting value > 0
- A negative number of mip maps is not allowed.
- ApplicationDataSubDirectory cannot be modified after the…
- ArgumentOutOfRangeException
- ArgumentOutOfRangeException
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/bad25f32e21ad9b1.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Effects/Compiler/EffectPriorityScheduler.cs:31
/// A <see cref="TaskScheduler"/> with control over concurrency and priority, useful with <see cref="EffectCompilerCache"/>.
/// </summary>
public class EffectPriorityScheduler : TaskScheduler, IDisposable
{
private static object lockObject = new object();
private ThreadPriority threadPriority;
private Thread[] threads;
private readonly int maximumConcurrencyLevel;
private readonly PriorityQueue<QueuedTask> taskPriorityQueue;
private readonly System.Collections.Generic.SortedList<int, PriorityGroupScheduler> priorityGroups = new System.Collections.Generic.SortedList<int, PriorityGroupScheduler>();
private readonly AutoResetEvent notifyQueuedTaskEvent = new AutoResetEvent(false);
private readonly AutoResetEvent notifyHighPriorityQueuedTaskEvent = new AutoResetEvent(false);
private readonly ManualResetEvent notifyThreadExitEvent = new ManualResetEvent(false);
private bool threadShouldExit;
public EffectPriorityScheduler(ThreadPriority threadPriority, int maximumConcurrencyLevel)
{
if (maximumConcurrencyLevel == 0)
throw new ArgumentOutOfRangeException("maximumConcurrencyLevel");
this.taskPriorityQueue = new PriorityQueue<QueuedTask>(new TaskPriorityComparer());
this.threadPriority = threadPriority;
this.maximumConcurrencyLevel = maximumConcurrencyLevel;
}
public int QueuedTaskCount { get { return taskPriorityQueue.Count; } }
/// <inheritdoc/>
public override int MaximumConcurrencyLevel
{
get { return maximumConcurrencyLevel; }
}
/// <inheritdoc/>
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{View on GitHub (pinned to 96fad776d2)