Overview
StateHasChanged()
is called to notify the Component that its state has changed. When applicable, calling this method can cause the Component to be rerendered.
This is necessary when the Component updates due to an external change (like an event from a service). In these cases, the Component does not update automatically.
StateHasChanged()
is called automatically for EventCallback
methods.
Problem
Credit: Blazor University
When code is called by a non-UI event, a thread locking/synchronization mechanism is normally required if we intend to manipulate state. Non-UI events include:
- A callback from a
System.Threading.Timer
- An event tirggered by another thread on a Singleton instance shared by multiple users
- A data push from another server we’ve connected to via a Web Socket
In WPF apps, Dispatcher.Invoke
ensures the UI thread executes the code. In WinForms, the Invoke
method of the form is used. This avoids the need to thread synchronizing code.
In Blazor Server, there is a single dispatched associated with each connection (browser tab). The StateHasChanged()
framework method throws an exception if a secondary thread accesses the rendering process at the same time.
Blazor WASM apps are single-threaded and so thread safety is not a concern.
Solution: InvokeAsync()
When calling StateHasChanged()
from one of the above scenarios, invoke it via the InvokeAsync()
method. InvokeAsync()
serializes the work.
Example
Wrap the call to StateHasChanged
in InvokeAsync()
:
InvokeAsync(StateHasChanged);
Disposal
Calling StateHasChanged()
is not supported in a Dispose()
method.