{"record":{"id":"2bbf571d592bb586","repo":"dotnet/reactive","slug":"the-current-thread-has-no-dispatcher-associated-with-it-2bbf57","errorCode":null,"errorMessage":"The current thread has no Dispatcher associated with it.","messagePattern":"The current thread has no Dispatcher associated with it\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive.Wpf/System.Reactive.Concurrency/DispatcherScheduler.cs","lineNumber":36,"sourceCode":"    /// 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.\n    /// </remarks>\n    public class DispatcherScheduler : LocalScheduler, ISchedulerPeriodic\n    {\n        /// <summary>\n        /// Gets the scheduler that schedules work on the current <see cref=\"System.Windows.Threading.Dispatcher\"/>.\n        /// </summary>\n        [Obsolete(Constants_WindowsThreading.OBSOLETE_INSTANCE_PROPERTY)]\n        public static DispatcherScheduler Instance => new(System.Windows.Threading.Dispatcher.CurrentDispatcher);\n\n        /// <summary>\n        /// Gets the scheduler that schedules work on the <see cref=\"System.Windows.Threading.Dispatcher\"/> for the current thread.\n        /// </summary>\n        public static DispatcherScheduler Current\n        {\n            get\n            {\n                var dispatcher = System.Windows.Threading.Dispatcher.FromThread(Thread.CurrentThread)\n                    ?? throw new InvalidOperationException(Strings_Wpf_WindowsThreading.NO_DISPATCHER_CURRENT_THREAD);\n                return new DispatcherScheduler(dispatcher);\n            }\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"DispatcherScheduler\"/> that schedules units of work on the given <see cref=\"System.Windows.Threading.Dispatcher\"/>.\n        /// </summary>\n        /// <param name=\"dispatcher\"><see cref=\"DispatcherScheduler\"/> to schedule work on.</param>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"dispatcher\"/> is <c>null</c>.</exception>\n        public DispatcherScheduler(System.Windows.Threading.Dispatcher dispatcher)\n        {\n            Dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));\n            Priority = System.Windows.Threading.DispatcherPriority.Normal;\n\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"DispatcherScheduler\"/> that schedules units of work on the given <see cref=\"System.Windows.Threading.Dispatcher\"/> at the given priority.","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive.Wpf/System.Reactive.Concurrency/DispatcherScheduler.cs#L18-L54","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar sched = DispatcherScheduler.Current; // throws on background thread\n// after\nvar sched = new DispatcherScheduler(Application.Current.Dispatcher);","handlingStrategy":"validation","validationCode":"bool canUseCurrent = System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread) != null;","typeGuard":"bool IsUiThread() => System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread) != null;","tryCatchPattern":"try { var sched = DispatcherScheduler.Current; } catch (InvalidOperationException ex) when (ex.Message.Contains(\"Dispatcher\")) { var sched = new DispatcherScheduler(Application.Current.Dispatcher); }","preventionTips":["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."],"tags":["wpf","dispatcher","threading","scheduler"],"backgroundTag":"missing-dispatcher-on-thread","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}