dotnet/reactive · error · ArgumentNullException

scheduler

Error message

scheduler

What it means

Thrown by ObserveOn(source, DispatcherScheduler) when the DispatcherScheduler argument is null. The operator reads scheduler.Dispatcher to obtain the target dispatcher; a null scheduler gives no scheduling target, so it fails fast with ArgumentNullException('scheduler').

Solutions

  1. Construct the scheduler explicitly: new DispatcherScheduler(dispatcher)
  2. Use Application.Current.Dispatcher to build the scheduler instead of relying on a null-propagating getter
  3. Guard the scheduler with a null check and fall back to a non-dispatcher scheduler

Example fix

// before
DispatcherScheduler sched = DispatcherScheduler.Current; // null off the UI thread
source.ObserveOn(sched);
// after
var sched = new DispatcherScheduler(Application.Current.Dispatcher);
source.ObserveOn(sched);
Defensive patterns

Strategy: validation

Validate before calling

var scheduler = sched ?? new DispatcherScheduler(Application.Current.Dispatcher);

Type guard

bool IsValidScheduler(DispatcherScheduler s) => s is not null && s.Dispatcher is not null;

Try / catch

try { stream.ObserveOn(scheduler).Subscribe(...); }
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { scheduler = new DispatcherScheduler(Application.Current.Dispatcher); }

Prevention

When it happens

Trigger: Passing a DispatcherScheduler variable that was never constructed, or one obtained from a factory/property that returned null when no dispatcher exists on the current thread.

Common situations: Using DispatcherScheduler.Current on a background thread without a dispatcher and caching a null result, or DI containers failing to resolve the scheduler instance.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/1be9b5d6cbe85f43. Report an issue: GitHub.

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/DispatcherObservable.cs:82

        /// <summary>
        /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher scheduler.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Source sequence.</param>
        /// <param name="scheduler">Dispatcher scheduler to notify observers on.</param>
        /// <returns>The source sequence whose observations happen on the specified dispatcher scheduler.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="scheduler"/> is null.</exception>
        public static IObservable<TSource> ObserveOn<TSource>(this IObservable<TSource> source, DispatcherScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

            return ObserveOn_(source, scheduler.Dispatcher, scheduler.Priority);
        }


        /// <summary>
        /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the specified object.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Source sequence.</param>
        /// <param name="dispatcherObject">Object to get the dispatcher from.</param>
        /// <returns>The source sequence whose observations happen on the specified object's dispatcher.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="dispatcherObject"/> is null.</exception>
        public static IObservable<TSource> ObserveOn<TSource>(this IObservable<TSource> source, DispatcherObject dispatcherObject)
        {
            if (source == null)
            {

View on GitHub (pinned to 94b5d5ab91)