dotnet/wpf · error · InvalidOperationException
SR.DispatcherProcessingDisabled
Error message
SR.DispatcherProcessingDisabled
What it means
Dispatcher.PushFrame throws InvalidOperationException with SR.DispatcherProcessingDisabled when the dispatcher's processing is currently disabled (its _disableProcessingCount is greater than zero), i.e. inside a Dispatcher.DisableProcessing scope. Message pumping is prohibited while processing is disabled to protect the dispatcher's internal state.
Solutions
- Move the PushFrame/ShowDialog/Invoke call outside the DisableProcessing scope.
- Remove the DisableProcessing wrapper if pumping is genuinely needed there.
- Disable processing only around short, non-reentrant code that never calls back into the dispatcher.
- Restructure so dependent work is queued with Dispatcher.InvokeAsync and executed after processing is re-enabled.
Example fix
// before
using (Dispatcher.CurrentDispatcher.DisableProcessing())
{
Dispatcher.PushFrame(new DispatcherFrame());
}
// after
Dispatcher.PushFrame(new DispatcherFrame()); // outside the disabled scope Defensive patterns
Strategy: validation
Validate before calling
// there is no public query; avoid pumping inside DisableProcessing scopes
using (Dispatcher.CurrentDispatcher.DisableProcessing())
{
DoAtomicWork(); // must not call ShowDialog/PushFrame/Invoke
}
Dispatcher.PushFrame(new DispatcherFrame()); // outside the scope Try / catch
try
{
Dispatcher.PushFrame(frame);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("processing"))
{
// we are inside DisableProcessing; defer the pump
} Prevention
- Never call ShowDialog, WaitForPriority, or PushFrame inside DisableProcessing blocks
- Keep DisableProcessing scopes short and free of reentrant dispatcher calls
- Run pump-needing code via Dispatcher.InvokeAsync to execute after processing is re-enabled
- Review callbacks invoked inside disabled scopes for UI operations
When it happens
Trigger: Calling PushFrame (directly or transitively, e.g. ShowDialog, WaitForPriority) inside a using Dispatcher.DisableProcessing() block, or inside code invoked under DispatcherProcessingDisabledMode; also raised from Invoke-like calls on the dispatcher while processing is disabled.
Common situations: Showing a modal dialog or pumping frames inside Dispatcher.DisableProcessing regions used for atomic updates; calling user code that pumps frames from within dispatcher-disabled sections (e.g. property change notifications during processing-disabled scopes).
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Processing is disabled while the Dispatcher is in this…
- SR.CollectionView_MissingSynchronizationCallback
- SR.ContextMenuInDifferentDispatcher
- SR.CurrentDispatcherNotFound
- SR.DispatcherHasShutdown
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/e3dba5330081d064.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Threading/Dispatcher.cs:314
/// </param>
public static void PushFrame(DispatcherFrame frame)
{
ArgumentNullException.ThrowIfNull(frame);
Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
if(dispatcher._hasShutdownFinished) // Dispatcher thread - no lock needed for read
{
throw new InvalidOperationException(SR.DispatcherHasShutdown);
}
if(frame.Dispatcher != dispatcher)
{
throw new InvalidOperationException(SR.MismatchedDispatchers);
}
if(dispatcher._disableProcessingCount > 0)
{
throw new InvalidOperationException(SR.DispatcherProcessingDisabled);
}
dispatcher.PushFrameImpl(frame);
}
/// <summary>
/// Requests that all nested frames exit.
/// </summary>
public static void ExitAllFrames()
{
Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
if(dispatcher._frameDepth > 0)
{
dispatcher._exitAllFrames = true;
// Post a message so that the message pump will wake up and
// check our continue state.View on GitHub (pinned to 81131a70a4)