- Notifications
You must be signed in to change notification settings - Fork1.9k
Rapid change of selected tab results in crash on Windows#32865
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Conversation
| WFrame?_navigationFrame; | ||
| bool_connectedToHandler; | ||
| bool_isUpdatingSelection; | ||
| bool_isNavigating; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
maybe these variables should be volatile?
volatile bool _isUpdatingSelection;volatile bool _isNavigating;There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
What is the reasoning behind using flags instead of some synchronization mechanism like a lock? I mean, if there is an operation that can not be run simultaneously, are the boolean flags sufficient? Or would it be better to use a Lock object and lock it? Or some kind of other synchronization like SemaphoreSlim?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@qjustfeelitp All operations run on the Windows UI thread:
- OnSelectedMenuItemChanged - WinUI SelectionChanged event (UI thread) - NavigateToPage - Called from UI thread - OnNavigated - WinUI navigation event (UI thread) - MapCurrentPage - Handler update (UI thread)WinUI guarantees these events are dispatched on the UI thread, so there's no concurrent multi-threaded access. The fix of adding flags prevents reentrant calls (the same thread calling again before completing).
Using synchronization primitives like lock or SemaphoreSlim would be overkill. Locking on the UI thread may cause deadlocks if any async operation awaits while holding the lock.
sheiksyedm commentedNov 28, 2025
/azp run MAUI-UITests-public |
| Azure Pipelines successfully started running 1 pipeline(s). |
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you couldtest the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Root Cause
When users rapidly switch tabs in TabbedPage on Windows, concurrent navigation operations cause a crash:
Stack trace shows crash at line 299 (
UpdateCurrentPageContent):WinRT.Runtime.dll!WinRT.ExceptionHelpers.ThrowExceptionForHR(int hr) Microsoft.W
inUI.dll!Microsoft.UI.Xaml.Controls.ContentPresenter.Content.set(object value) M
icrosoft.Maui.Controls.dll!Microsoft.Maui.Controls.TabbedPage.UpdateCurrentPageC
ontent(WPage page) Line 299
The Problem Flow:
1. User rapidly clicks tabs (Tab 1 → Tab 2 → Tab 3)
2. First tab change calls
NavigateToPage→NavigationFrame.NavigateToType()3. Navigation starts,
OnNavigatedevent will fire when complete4.Before first navigation completes, second tab change triggers another
NavigateToPage5. Second navigation also calls
NavigateToType()→ starts another navigation6. Both
OnNavigatedevents fire and try to setpresenter.Content7.WinUI throws:
ContentPresenter.Contentcannot be modified during active navigation/layout operationAdditionally, setting
SelectedIteminMapCurrentPagetriggersSelectionChangedevents that cause reentrant calls.Solution
Implemented two guard flags to prevent race conditions:
_isNavigatingflag - Prevents overlapping navigation operations- Set before calling
NavigateToType()- Checked at start of
NavigateToPage()- returns early if navigation in progress- Cleared in
OnNavigated()finally block after content update completes_isUpdatingSelectionflag - Prevents reentrant selection events- Set before updating
SelectedIteminMapCurrentPage- Checked at start of
OnSelectedMenuItemChanged- returns early if updating programmatically- Cleared in finally block after update completes
This ensures:
- Only one navigation operation runs at a time
- Subsequent rapid clicks are queued/ignored until current navigation completes
- No reentrant selection change events
- Safe cleanup via try-finally blocks
Fixes#32824