Skip to content

ParameterState: Add Snapshot to avoid race condition#12023

Merged
ScarletKuro merged 5 commits into
MudBlazor:devfrom
ScarletKuro:param_race
Oct 30, 2025
Merged

ParameterState: Add Snapshot to avoid race condition#12023
ScarletKuro merged 5 commits into
MudBlazor:devfrom
ScarletKuro:param_race

Conversation

@ScarletKuro

@ScarletKuro ScarletKuro commented Oct 30, 2025

Copy link
Copy Markdown
Member

From discord:

It seems to be linked to some code I did to track a selected item id by updating the url with NavigateTo when it changes, but I'm confused about what it actually happening. I can't get it to work on TryMudBlazor, so here is an archive of a basic project that display this behavior: BugProject.zip

Explanation:
It looks like this is caused by Navigation.NavigateTo.
What I’m seeing is that when the page initializes, it calls Blazor’s SetParametersAsync, which tells us the parameters changed and queues that info up. But then, because of the NavigateTo, another SetParametersAsync fires almost right away, before the first one even finishes. At that point, it sees that the parameter was already set to the same value, since it reuses same ParameterStateInternal reference and removes the info that parameter changed:

_parameterChangedEventArgs = null;

Then, when the first SetParametersAsync gets to finish to call the change handler it sees no changes (since it was already cleared earlier by second SetParametersAsync), and doesn’t trigger ParameterChangeHandleAsync.

Checklist:

  • The PR is submitted to the correct branch (dev).
  • My code follows the style of this project.
  • I've added relevant tests or confirmed existing ones.

@ScarletKuro

Copy link
Copy Markdown
Member Author

Missing a unit test for now, but it does fixes the reproduction project.

@mudbot mudbot Bot added bug Unexpected behavior or functionality not working as intended needs: tests A maintainer has explicitly asked for test cases to be added labels Oct 30, 2025

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a snapshot mechanism to the ParameterState framework to address a race condition that can occur with rapid, successive calls to SetParametersAsync. By creating an immutable snapshot of the parameter's state when a change is detected, the change handler can be invoked safely later, preventing state corruption from concurrent updates. The implementation is clean, well-documented, and correctly isolates the state for asynchronous handler execution. The changes are logically sound and include necessary updates to tests, interfaces, and container classes to support the new snapshot pattern. Overall, this is an excellent improvement to the robustness of the framework.

Comment thread src/MudBlazor/State/Invocation/ParameterStateInvocationSnapshot.cs Outdated
@ScarletKuro
ScarletKuro requested a review from Copilot October 30, 2025 20:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a snapshot mechanism to capture parameter invocation state before handlers are executed, preventing race conditions when concurrent SetParametersAsync calls occur. The key change is that instead of directly invoking handlers on live state, the code now creates immutable snapshots containing cloned event arguments and handler references.

  • Replaces direct handler invocation with snapshot-based deferred execution
  • Introduces IParameterStateInvocationSnapshot interface and ParameterStateInvocationSnapshot<T> implementation
  • Adds Clone() method to ParameterChangedEventArgs<T> for safe state capture

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
ParameterStateInternalOfT.cs Replaces ParameterChangeHandleAsync() with CreateInvocationSnapshot() to capture state for deferred invocation
ParameterScopeContainer.cs Updates to create snapshots before baseSetParametersAsync and invoke handlers from snapshots
ParameterContainer.cs Adds snapshot creation step in parameter change detection pipeline
ParameterChangedEventArgs.cs Adds Clone() method to create independent copies of event arguments
ParameterStateInvocationSnapshot.cs New class implementing snapshot-based handler invocation with captured state
IParameterStateInvocationSnapshot.cs New interface defining contract for parameter invocation snapshots
IParameterComponentLifeCycle.cs Updates interface to replace ParameterChangeHandleAsync() with CreateInvocationSnapshot()
ParameterHandlerUniquenessComparer.cs Extends comparer to support IParameterStateInvocationSnapshot equality checks
ParameterStateTests.cs Updates tests to use new snapshot-based invocation pattern
ParameterHandlerUniquenessComparerTests.cs Adds test coverage for snapshot equality and hash code operations
ParameterContainerTests.cs Adds new test verifying snapshot mechanism prevents race condition issues

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ScarletKuro
ScarletKuro merged commit 08eaa85 into MudBlazor:dev Oct 30, 2025
12 checks passed
@ScarletKuro ScarletKuro removed the needs: tests A maintainer has explicitly asked for test cases to be added label Oct 30, 2025
@ScarletKuro
ScarletKuro deleted the param_race branch October 30, 2025 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Unexpected behavior or functionality not working as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants