dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'control')
Error message
Value cannot be null. (Parameter 'control')
What it means
The ControlScheduler constructor stores the Windows Forms Control on which work will be invoked via control.BeginInvoke, so a null control is rejected immediately with ArgumentNullException. ControlScheduler cannot function without a control because it uses the control's handle/thread to marshal execution.
Solutions
- Pass a valid, constructed Control instance (e.g. the form or a control on it).
- Check for null before constructing: if (control == null) throw/log instead.
- Ensure InitializeComponent has run so designer control fields are assigned before scheduler creation.
Example fix
// before
var scheduler = new ControlScheduler(_myControl); // _myControl null before InitializeComponent
// after
InitializeComponent();
if (_myControl == null) throw new InvalidOperationException("control not initialized");
var scheduler = new ControlScheduler(_myControl); Defensive patterns
Strategy: validation
Validate before calling
if (control == null || control.IsDisposed) throw new InvalidOperationException("A live WinForms control is required");
var scheduler = new ControlScheduler(control); Type guard
static bool HasControl(Control c) => c is not null && !c.IsDisposed;
Try / catch
try { var s = new ControlScheduler(control); } catch (ArgumentNullException ex) when (ex.ParamName == "control") { /* log missing control dependency */ } Prevention
- Construct schedulers after InitializeComponent so control fields exist
- Assert control dependencies at injection time
- Prefer ObserveOn(control)/SubscribeOn(control) helpers over manual scheduler construction
When it happens
Trigger: new ControlScheduler(null), or passing a Control field/property that is null (e.g. a form control accessed before InitializeComponent or from a context where the control reference was never assigned).
Common situations: Constructor injection where the WinForms control dependency was not registered; using this.SomeControl in a control whose designer field is not yet initialized; unit tests constructing the scheduler without a real control.
Related errors
- Value cannot be null. (Parameter 'action')
- Value cannot be null. (Parameter 'action')
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'scheduler')
- scheduler
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/46b1b9c245d36220.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Concurrency/ControlScheduler.cs:28
{
/// <summary>
/// Represents an object that schedules units of work on the message loop associated with a Windows Forms control.
/// </summary>
public class ControlScheduler : LocalScheduler, ISchedulerPeriodic
{
private readonly Control _control;
/// <summary>
/// Constructs a ControlScheduler that schedules units of work on the message loop associated with the specified Windows Forms control.
/// </summary>
/// <param name="control">Windows Forms control to get the message loop from.</param>
/// <exception cref="ArgumentNullException"><paramref name="control"/> is null.</exception>
/// <remarks>
/// This scheduler type is typically used indirectly through the <see cref="Linq.ControlObservable.ObserveOn{TSource}"/> and <see cref="Linq.ControlObservable.SubscribeOn{TSource}"/> method overloads that take a Windows Forms control.
/// </remarks>
public ControlScheduler(Control control)
{
_control = control ?? throw new ArgumentNullException(nameof(control));
}
/// <summary>
/// Gets the control associated with the ControlScheduler.
/// </summary>
public Control Control => _control;
/// <summary>
/// Schedules an action to be executed on the message loop associated with the control.
/// </summary>
/// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam>
/// <param name="state">State passed to the action to be executed.</param>
/// <param name="action">Action to be executed.</param>
/// <returns>The disposable object used to cancel the scheduled action (best effort).</returns>
/// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
public override IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
{
if (action == null)View on GitHub (pinned to 94b5d5ab91)