{"record":{"id":"e70561c70164b038","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-action-controlscheduler","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'action')","messagePattern":"Value cannot be null\\. \\(Parameter 'action'\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/ControlScheduler.cs","lineNumber":48,"sourceCode":"\n        /// <summary>\n        /// Gets the control associated with the ControlScheduler.\n        /// </summary>\n        public Control Control => _control;\n\n        /// <summary>\n        /// Schedules an action to be executed on the message loop associated with the control.\n        /// </summary>\n        /// <typeparam name=\"TState\">The type of the state passed to the scheduled action.</typeparam>\n        /// <param name=\"state\">State passed to the action to be executed.</param>\n        /// <param name=\"action\">Action to be executed.</param>\n        /// <returns>The disposable object used to cancel the scheduled action (best effort).</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"action\"/> is null.</exception>\n        public override IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)\n        {\n            if (action == null)\n            {\n                throw new ArgumentNullException(nameof(action));\n            }\n\n            if (_control.IsDisposed)\n            {\n                return Disposable.Empty;\n            }\n\n            var d = new SingleAssignmentDisposable();\n\n            _control.BeginInvoke(new Action(() =>\n            {\n                if (!_control.IsDisposed && !d.IsDisposed)\n                {\n                    d.Disposable = action(this, state);\n                }\n            }));\n\n            return d;","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/ControlScheduler.cs#L30-L66","documentation":"ControlScheduler.Schedule<TState>(state, action) invokes the action on the scheduler's control thread and therefore requires a non-null action delegate. The ArgumentNullException guard runs before the IsDisposed check, so a null action always throws even if the control is already disposed.","triggerScenarios":"Calling scheduler.Schedule(state, null) directly, or Rx operators receiving a null work delegate, e.g. a lambda variable that was never assigned or a Func field left null after refactoring.","commonSituations":"Building schedules dynamically from a dictionary of delegates where the lookup missed; passing a method group whose containing object method is conditionally compiled out; typo passing wrong argument order so null lands in the action parameter.","solutions":["Pass a non-null delegate: scheduler.Schedule(state, (sched, st) => { ...; return Disposable.Empty; }).","Guard the delegate before scheduling and fall back to a no-op returning Disposable.Empty.","Verify argument order in the Schedule call so a state value is not passed where the Func is expected."],"exampleFix":"// before\nscheduler.Schedule(state, _work); // _work null\n// after\nvar work = _work ?? ((sched, st) => Disposable.Empty);\nscheduler.Schedule(state, work);","handlingStrategy":"validation","validationCode":"if (action == null) action = (sched, st) => Disposable.Empty;\nscheduler.Schedule(state, action);","typeGuard":"static bool HasWork<TState>(Func<IScheduler, TState, IDisposable> a) => a is not null;","tryCatchPattern":"try { scheduler.Schedule(state, action); } catch (ArgumentNullException ex) when (ex.ParamName == \"action\") { /* substitute no-op or log */ }","preventionTips":["Initialize delegate fields at declaration or in the constructor","Check argument order in Schedule calls","Use Observer/Disposable helpers for default no-op delegates"],"tags":["dotnet","winforms","null-argument","scheduler"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}