{"record":{"id":"025fcdc96d23f02f","repo":"HangfireIO/Hangfire","slug":"taskscheduler","errorCode":null,"errorMessage":"taskScheduler","messagePattern":"taskScheduler","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.Core/Processing/BackgroundDispatcherAsync.cs","lineNumber":52,"sourceCode":"        private readonly object _state;\n\n        private readonly TaskScheduler _taskScheduler;\n        private readonly bool _ownsScheduler;\n\n        public BackgroundDispatcherAsync(\n            [NotNull] IBackgroundExecution execution,\n            [NotNull] Func<Guid, object, Task> action,\n            [CanBeNull] object state,\n            [NotNull] TaskScheduler taskScheduler,\n            int maxConcurrency,\n            bool ownsScheduler)\n        {\n            if (maxConcurrency <= 0) throw new ArgumentOutOfRangeException(nameof(maxConcurrency));\n\n            _execution = execution ?? throw new ArgumentNullException(nameof(execution));\n            _action = action ?? throw new ArgumentNullException(nameof(action));\n            _state = state;\n            _taskScheduler = taskScheduler ?? throw new ArgumentNullException(nameof(taskScheduler));\n            _ownsScheduler = ownsScheduler;\n\n#if !NETSTANDARD1_3\n            AppDomainUnloadMonitor.EnsureInitialized();\n#endif\n\n            _stopped = new CountdownEvent(maxConcurrency);\n\n            for (var i = 0; i < maxConcurrency; i++)\n            {\n                Task.Factory.StartNew(\n                    DispatchLoop,\n                    CancellationToken.None,\n                    TaskCreationOptions.None,\n                    _taskScheduler).Unwrap();\n            }\n        }\n","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.Core/Processing/BackgroundDispatcherAsync.cs#L34-L70","documentation":"Thrown by BackgroundDispatcherAsync's constructor (internal) when the TaskScheduler argument is null. The dispatcher schedules each dispatch loop task onto that scheduler (Task.Factory.StartNew(..., _taskScheduler)), so a null scheduler has nowhere to run.","triggerScenarios":"Constructing BackgroundDispatcherAsync with taskScheduler == null. Happens when the caller passes a null BackgroundTaskScheduler or TaskScheduler.Default resolution failed.","commonSituations":"A hosting extension resolves the scheduler lazily and the resolution returned null; a custom server builder omitted the scheduler argument; DI container misregistration for the scheduler service.","solutions":["Pass a non-null TaskScheduler — typically a BackgroundTaskScheduler instance or TaskScheduler.Default.","Resolve the scheduler before constructing the dispatcher and validate it is non-null.","Fix the DI registration so the scheduler service is always provided."],"exampleFix":"// before\nvar dispatcher = new BackgroundDispatcherAsync(execution, action, state, null, 4, false);\n\n// after\nvar scheduler = scheduler ?? new BackgroundTaskScheduler();\nvar dispatcher = new BackgroundDispatcherAsync(execution, action, state, scheduler, 4, ownsScheduler: true);","handlingStrategy":"validation","validationCode":"TaskScheduler scheduler = resolvedScheduler ?? new BackgroundTaskScheduler();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default to a BackgroundTaskScheduler or TaskScheduler.Default when none is supplied.","Resolve the scheduler before building the dispatcher.","Check DI registration for the scheduler service."],"tags":["hangfire","null-argument","argument-validation","task-scheduler","background-processing"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}