dotnet/reactive · error · InvalidOperationException
The current thread has no Dispatcher associated with it.
Error message
The current thread has no Dispatcher associated with it.
What it means
DispatcherScheduler.Current is a convenience accessor that grabs the Dispatcher of the calling thread via Dispatcher.FromThread. If the current thread has no Dispatcher (i.e. it is not a WPF UI thread), it throws InvalidOperationException with the NO_DISPATCHER_CURRENT_THREAD message.
Solutions
- Call DispatcherScheduler.Current only on the WPF UI thread; capture it once on the UI thread (e.g. in App startup) and reuse that instance.
- Construct the scheduler explicitly with the UI dispatcher: new DispatcherScheduler(Application.Current.Dispatcher) or DispatcherScheduler.From dispatcher of the Window.
- Use ObserveOnDispatcher()/SubscribeOnDispatcher() extension methods from within WPF code instead of manually fetching Current.
Example fix
// before var sched = DispatcherScheduler.Current; // throws on background thread // after var sched = new DispatcherScheduler(Application.Current.Dispatcher);
Defensive patterns
Strategy: validation
Validate before calling
bool canUseCurrent = System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread) != null;
Type guard
bool IsUiThread() => System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread) != null;
Try / catch
try { var sched = DispatcherScheduler.Current; } catch (InvalidOperationException ex) when (ex.Message.Contains("Dispatcher")) { var sched = new DispatcherScheduler(Application.Current.Dispatcher); } Prevention
- Capture the UI scheduler once at application startup and inject it.
- Use ObserveOnDispatcher()/SubscribeOnDispatcher() rather than constructing schedulers ad hoc.
- Never reference DispatcherScheduler.Current inside operators running on TaskPool/NewThread schedulers.
When it happens
Trigger: Accessing DispatcherScheduler.Current from a background/thread-pool thread, a Task worker, a console Main thread, or any non-WPF thread where Dispatcher.FromThread returns null.
Common situations: Calling Current inside Subscribe callbacks or Rx operators that run on the thread-pool scheduler; unit tests running on plain MSTest/xUnit threads; building the scheduler during app startup before the UI thread is active.
Related errors
- Value cannot be null. (Parameter 'dispatcher')
- threadFactory (Parameter 'threadFactory')
- action (Parameter 'action')
- The current thread has no Dispatcher associated with it.
- Value cannot be null. (Parameter 'dispatcher')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/2bbf571d592bb586.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive.Wpf/System.Reactive.Concurrency/DispatcherScheduler.cs:36
/// This scheduler type is typically used indirectly through the <see cref="Linq.DispatcherObservable.ObserveOnDispatcher{TSource}(IObservable{TSource})"/> and <see cref="Linq.DispatcherObservable.SubscribeOnDispatcher{TSource}(IObservable{TSource})"/> methods that use the Dispatcher on the calling thread.
/// </remarks>
public class DispatcherScheduler : LocalScheduler, ISchedulerPeriodic
{
/// <summary>
/// Gets the scheduler that schedules work on the current <see cref="System.Windows.Threading.Dispatcher"/>.
/// </summary>
[Obsolete(Constants_WindowsThreading.OBSOLETE_INSTANCE_PROPERTY)]
public static DispatcherScheduler Instance => new(System.Windows.Threading.Dispatcher.CurrentDispatcher);
/// <summary>
/// Gets the scheduler that schedules work on the <see cref="System.Windows.Threading.Dispatcher"/> for the current thread.
/// </summary>
public static DispatcherScheduler Current
{
get
{
var dispatcher = System.Windows.Threading.Dispatcher.FromThread(Thread.CurrentThread)
?? throw new InvalidOperationException(Strings_Wpf_WindowsThreading.NO_DISPATCHER_CURRENT_THREAD);
return new DispatcherScheduler(dispatcher);
}
}
/// <summary>
/// Constructs a <see cref="DispatcherScheduler"/> that schedules units of work on the given <see cref="System.Windows.Threading.Dispatcher"/>.
/// </summary>
/// <param name="dispatcher"><see cref="DispatcherScheduler"/> to schedule work on.</param>
/// <exception cref="ArgumentNullException"><paramref name="dispatcher"/> is <c>null</c>.</exception>
public DispatcherScheduler(System.Windows.Threading.Dispatcher dispatcher)
{
Dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
Priority = System.Windows.Threading.DispatcherPriority.Normal;
}
/// <summary>
/// Constructs a <see cref="DispatcherScheduler"/> that schedules units of work on the given <see cref="System.Windows.Threading.Dispatcher"/> at the given priority.View on GitHub (pinned to 94b5d5ab91)