dotnet/reactive · error · ArgumentNullException

dispatcher

Error message

dispatcher

What it means

The second validation in DispatcherObservable.ObserveOn throws ArgumentNullException with parameter name 'dispatcher' when the WPF Dispatcher is null. The dispatcher is required to post observer callbacks to the UI thread.

Solutions

  1. Pass a valid non-null Dispatcher, e.g. Application.Current.Dispatcher or the window's Dispatcher.
  2. Capture the dispatcher on the UI thread at startup and store it, rather than resolving lazily.
  3. In tests, provide a dispatcher via a DispatcherSynchronizationContext or a test scheduler instead of null.

Example fix

// before
source.ObserveOn(Application.Current.Dispatcher).Subscribe(OnNext); // Application.Current is null in tests
// after
var dispatcher = Application.Current?.Dispatcher ?? _uiDispatcher;
source.ObserveOn(dispatcher).Subscribe(OnNext);
Defensive patterns

Strategy: validation

Validate before calling

var dispatcher = Application.Current?.Dispatcher
                 ?? (System.Windows.Threading.Dispatcher.FromThread(Thread.CurrentThread)
                     ?? Dispatcher.CurrentDispatcher);
if (dispatcher == null) throw new InvalidOperationException("No WPF dispatcher available");
source.ObserveOn(dispatcher).Subscribe(OnNext);

Type guard

static bool HasDispatcher(Dispatcher d) => d is not null && !d.HasShutdownStarted;

Try / catch

try { source.ObserveOn(dispatcher).Subscribe(OnNext); }
catch (ArgumentNullException ex) when (ex.ParamName == "dispatcher") { log.Error("Dispatcher was null at ObserveOn"); }

Prevention

When it happens

Trigger: Calling source.ObserveOn(null) — e.g. Dispatcher.CurrentDispatcher captured before the UI thread existed, Application.Current null in tests, or a control's Dispatcher accessed after the control was disposed.

Common situations: Unit tests without a WPF application context (Application.Current is null); background threads that never created a dispatcher; shutdown races where the window's Dispatcher is already gone.

Related errors


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

Appendix: source

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

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

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

            return ObserveOn_(source, dispatcher);
        }

        /// <summary>
        /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Source sequence.</param>
        /// <param name="dispatcher">Dispatcher whose associated message loop is used to notify observers on.</param>
        /// <param name="priority">Priority to schedule work items at.</param>
        /// <returns>The source sequence whose observations happen on the specified dispatcher.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="dispatcher"/> is null.</exception>
        public static IObservable<TSource> ObserveOn<TSource>(this IObservable<TSource> source, Dispatcher dispatcher, DispatcherPriority priority)
        {
            if (source == null)
            {

View on GitHub (pinned to 94b5d5ab91)