Hi @水 知 , thanks for reaching us on this platform!
When should I use dispatcher?
In WinUI 3, UI elements must only be accessed from the UI thread. If code runs on a background thread (Task.Run, async database calls...) and tries to touch the UI, you will get exceptions. This is when you use Dispatcher.
- You update UI from code running on a background thread
- Your async method resumes on a non-UI thread
When I browsing the sample codes I never found them using dispatcher
Most sample code simply runs on the UI thread or uses async/await that automatically returns to UI context.
but sometimes my app will crash if I don't use dispatcher in some places.
Your app crashes because after await, it sometimes runs on a background thread, and background thread are not allowed to touch the UI. So, the dispatcher is needed to move the code back to the UI thread before updating controls.
When should I unsubscribe events?
You should unsubscribe events whenever the subscriber (your control or page) may be garbage-collected but the publisher lives longer.
- If the event source outlives the subscriber, unsubscribe them.
Controls that are children of ListView/GridView or templates must unsubscribe, because virtualization reuses and removes controls.
Where to unsubscribe:
- Do NOT rely on finalizers (~ClassName) because WinUI controls often never run them reliably.
- Do NOT rely on Dispose() as controls in WinUI do not implement Dispose.
Do unsubscribe in Unloaded or OnNavigatedFrom, depending on the control type.
Here is an example for templated child control generated by Copilot:
public MyChildControl()
{
Loaded += OnLoaded;
Unloaded += OnUnloaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
SomeService.DataChanged += OnDataChanged;
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
SomeService.DataChanged -= OnDataChanged;
}
For a templated control, if it’s a child control of another control, should I unsubscribe the events when the control is being disposed?
Yes, always unsubscribe.
"Being disposed" in WinUI is actually when Unloaded fires or the parent control removes the child.
Finalizers should never be used for event cleanup as they are too late and unreliable in WinUI.
Where to unsubscribe (mentioned above)
And how to unsubscribe the anonymous functions?
You cannot unsubscribe directly, because there is no reference to it.
The correct approach is storing the delegate in a variable and unsubscribe later.
Here is an example generated by Copilot:
private RoutedEventHandler _handler;
public MyControl()
{
_handler = (s, e) => DoWork();
Button.Click += _handler;
}
public void Cleanup()
{
Button.Click -= _handler;
}