dotnet/wpf · error · InvalidOperationException
SR.MismatchedDispatchers
Error message
SR.MismatchedDispatchers
What it means
Dispatcher.PushFrame throws InvalidOperationException with SR.MismatchedDispatchers when the DispatcherFrame passed in was created for (or associated with) a different Dispatcher than the one running on the current thread. Each frame records its owning Dispatcher, and PushFrame validates frame.Dispatcher == Dispatcher.CurrentDispatcher before pushing.
Solutions
- Create a new DispatcherFrame on the same thread you call PushFrame from.
- Ensure the frame's Dispatcher equals Dispatcher.CurrentDispatcher before pushing.
- Stop sharing frame instances across threads; make frames thread-local.
- If cross-thread work is intended, use Dispatcher.Invoke/InvokeAsync on the target dispatcher instead of pumping its frame from another thread.
Example fix
// before private static readonly DispatcherFrame _frame = new DispatcherFrame(); Dispatcher.PushFrame(_frame); // after Dispatcher.PushFrame(new DispatcherFrame()); // created on the calling thread
Defensive patterns
Strategy: validation
Validate before calling
if (frame.Dispatcher != Dispatcher.CurrentDispatcher)
frame = new DispatcherFrame(); // recreate on this thread
Dispatcher.PushFrame(frame); Type guard
bool IsFrameForCurrentThread(DispatcherFrame f) => f.Dispatcher == Dispatcher.CurrentDispatcher;
Prevention
- Never cache DispatcherFrame instances in static/shared fields
- Create frames at the point of use, on the calling thread
- Document that frames are thread-affine like all Dispatcher objects
- Prefer Invoke/InvokeAsync for cross-thread work instead of pumping another thread's dispatcher
When it happens
Trigger: Calling PushFrame on thread A with a DispatcherFrame whose Dispatcher property points to thread B's dispatcher — typically a frame captured or created on another thread, or a shared static frame reused across threads.
Common situations: Caching a DispatcherFrame in a static/shared field and pumping it from multiple threads; creating a frame on the UI thread and pushing it from a worker; borrowing frames across modal-dialog helpers.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 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/6c6e085e9abe2c21.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Threading/Dispatcher.cs:309
/// <summary>
/// Push an execution frame.
/// </summary>
/// <param name="frame">
/// The frame for the dispatcher to process.
/// </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)View on GitHub (pinned to 81131a70a4)