{"record":{"id":"319a4981cab5034b","repo":"HangfireIO/Hangfire","slug":"threadfactory","errorCode":null,"errorMessage":"threadFactory","messagePattern":"threadFactory","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.Core/Processing/BackgroundDispatcher.cs","lineNumber":45,"sourceCode":"\nnamespace Hangfire.Processing\n{\n    internal sealed class BackgroundDispatcher : IBackgroundDispatcher\n    {\n        private readonly ILog _logger = LogProvider.GetLogger(typeof(BackgroundDispatcher));\n        private readonly CountdownEvent _stopped;\n\n        private readonly IBackgroundExecution _execution;\n        private readonly Action<Guid, object> _action;\n        private readonly object _state;\n\n        public BackgroundDispatcher(\n            [NotNull] IBackgroundExecution execution,\n            [NotNull] Action<Guid, object> action,\n            [CanBeNull] object state,\n            [NotNull] Func<ThreadStart, IEnumerable<Thread>> threadFactory)\n        {\n            if (threadFactory == null) throw new ArgumentNullException(nameof(threadFactory));\n\n            _execution = execution ?? throw new ArgumentNullException(nameof(execution));\n            _action = action ?? throw new ArgumentNullException(nameof(action));\n            _state = state;\n\n#if !NETSTANDARD1_3\n            AppDomainUnloadMonitor.EnsureInitialized();\n#endif\n\n            var threads = threadFactory(DispatchLoop)?.ToArray();\n\n            if (threads == null || threads.Length == 0)\n            {\n                throw new ArgumentException(\"At least one unstarted thread should be created.\", nameof(threadFactory));\n            }\n\n            if (threads.Any(static thread => thread == null || (thread.ThreadState & ThreadState.Unstarted) == 0))\n            {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.Core/Processing/BackgroundDispatcher.cs#L27-L63","documentation":"Thrown as ArgumentNullException by the BackgroundDispatcher constructor when the 'threadFactory' Func<ThreadStart, IEnumerable<Thread>> argument is null. BackgroundDispatcher is an internal worker that spawns one or more threads to run the dispatch loop; the threadFactory is the only way to create those threads, so a null factory aborts construction at line 45.","triggerScenarios":"Constructing a BackgroundDispatcher with a null threadFactory. This is an internal API normally invoked by the Hangfire processing machinery (BackgroundJobServer/processing server) with a framework-supplied factory; a null factory would only arise from a custom/derived processing server or a reflection-based instantiation that did not supply one.","commonSituations":"A custom processing server that manually instantiates BackgroundDispatcher with a null factory; a test that constructs the dispatcher without a thread factory; a reflection/serialization path that omits the argument. End users of BackgroundJobServer do not pass this argument directly.","solutions":["If you maintain a custom processing server, supply a non-null threadFactory (e.g. start => new[] { new Thread(start) { IsBackground = true } }).","Use the public BackgroundJobServer API instead of constructing internal dispatchers directly, so the factory is provided for you.","Ensure any test helper that builds a BackgroundDispatcher passes a valid factory that returns unstarted threads."],"exampleFix":"// before\nvar d = new BackgroundDispatcher(execution, action, state, null);\n\n// after\nFunc<ThreadStart, IEnumerable<Thread>> factory =\n    start => new[] { new Thread(start) { IsBackground = true } };\nvar d = new BackgroundDispatcher(execution, action, state, factory);","handlingStrategy":"validation","validationCode":"if (threadFactory == null) throw new ArgumentNullException(nameof(threadFactory));\nFunc<ThreadStart, IEnumerable<Thread>> factory =\n    start => new[] { new Thread(start) { IsBackground = true } };","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the public BackgroundJobServer API instead of constructing internal dispatchers.","In custom servers/tests, always supply a factory that returns at least one unstarted thread."],"tags":["argument-null","processing","threading","internal-api"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}