Fix XamlMessageBox STA Threading Crash from Background Threads#2400
Merged
brianrob merged 3 commits intomicrosoft:mainfrom Mar 27, 2026
Merged
Fix XamlMessageBox STA Threading Crash from Background Threads#2400brianrob merged 3 commits intomicrosoft:mainfrom
brianrob merged 3 commits intomicrosoft:mainfrom
Conversation
XamlMessageBox.Show() now auto-dispatches to the UI thread when called from a background thread, matching the old System.Windows.MessageBox behavior. This fixes the SecurityCheck delegate crash during symbol resolution, where the delegate is invoked on Task.Run threads. The fix checks Application.Current.Dispatcher.CheckAccess() and uses synchronous Dispatcher.Invoke to marshal the call, preserving the return value for callers. Existing UI-thread call sites are unaffected (CheckAccess returns true, no dispatch needed). Fixes microsoft#2300 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ingleton, guard RegisterClassHandler - XamlMessageBox.cs: Use owner?.Dispatcher ?? Application.Current?.Dispatcher so the dispatch targets the correct UI thread when an owner window is provided. Simplify with Dispatcher.Invoke(Func<T>) to return result directly. - XamlMessageBoxTests.cs: Guard Application creation with Application.Current ?? to prevent InvalidOperationException in shared AppDomains. - XamlMessageBoxTests.cs: Add static guard for RegisterClassHandler (permanent, AppDomain-wide registration) and use XamlMBTest_ prefix for unique captions. - XamlMessageBoxTests.cs: Use indexer assignment for theme resources (idempotent). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…spatcher in test Replace app.Dispatcher.BeginInvoke with Dispatcher.CurrentDispatcher.BeginInvoke to ensure work is queued to the dispatcher being pumped by Dispatcher.Run(). If Application.Current was reused from a prior test on a different thread, app.Dispatcher would target that thread's dispatcher, causing the test to hang. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1825169 to
36558d0
Compare
marklio
approved these changes
Mar 27, 2026
This was referenced Mar 31, 2026
Merged
This was referenced Apr 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #2300 —
XamlMessageBox.Show()now auto-dispatches to the UI thread when called from a background thread, matching the oldSystem.Windows.MessageBoxbehavior.Problem
PR #2276 replaced
System.Windows.MessageBox(Win32 API, no thread affinity) withXamlMessageBox(WPFShowDialog(), requires STA/UI thread). Several call sites invokeXamlMessageBox.Show()from background threads — most notably theSecurityCheckdelegate inApp.cs, which runs during symbol resolution onTask.Runthreads. This causes:Fix
Added auto-dispatch logic to the core
XamlMessageBox.Show()overload (all 10+ overloads funnel through this single method):owner?.Dispatcher ?? Application.Current?.Dispatcher!CheckAccess()), uses synchronousDispatcher.Invoketo marshal the callTesting
XamlMessageBoxTests.cswith a regression test that exercises both UI-thread and background-threadShow()callsEventManager.RegisterClassHandlerto auto-close dialogs, and verifies no exceptions are thrown