Marshal iOS/Droid chart redraws to the UI thread; remove dead PlanifyInvalidate (#245)#381
Merged
Merged
Conversation
…yInvalidate The native iOS and Android ChartViews invalidated directly on whatever thread a chart property was changed on, so updating a chart from a background thread (e.g. a polling task) called UIKit/Android draw APIs off the UI thread and crashed. The MAUI view already dispatches via Dispatcher.Dispatch; bring the native views in line: - iOS: BeginInvokeOnMainThread(InvalidateChart) - Droid: PostInvalidate() (safe from any thread) instead of Invalidate() Also remove the async void PlanifyInvalidate method (and its unused invalidationPlanification field) called out in the issue - it had no call sites anywhere in the repo. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR improves runtime stability when chart properties are mutated off the UI thread by ensuring iOS/Android view redraw requests are marshaled safely to their UI threads, and removes unused invalidation debouncing code from the core Chart type.
Changes:
- Removed the unused
PlanifyInvalidatemethod and its backinginvalidationPlanificationfield fromChart. - iOS
ChartViewnow dispatches redraws viaBeginInvokeOnMainThread(...)when the chart raisesInvalidated. - Android
ChartViewnow usesPostInvalidate()(thread-safe) instead ofInvalidate()when the chart raisesInvalidated.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| Sources/Microcharts/Charts/Chart.cs | Removes dead invalidation planification logic and keeps invalidation signaling simple. |
| Sources/Microcharts.iOS/ChartView.cs | Marshals chart invalidation-driven redraws to the main UI thread. |
| Sources/Microcharts.Droid/ChartView.cs | Uses thread-safe PostInvalidate() for chart invalidation-driven redraws. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Addresses Copilot review on #381: the Chart setter still invalidated directly on the calling thread, so assigning Chart from a background thread could redraw off the UI thread. Marshal the setter's invalidate as well - BeginInvokeOnMainThread on iOS, PostInvalidate on Droid - consistent with the invalidation handler. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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
Addresses the two problems behind #245 ("Chart presumes properties are always changed on the UI thread; exceptions lost in
async void PlanifyInvalidate").1.
PlanifyInvalidatewas dead code. Theasync void PlanifyInvalidatemethod the issue called out has no call sites anywhere in the repo. Removed it (and its now-unusedinvalidationPlanificationfield).2. The native iOS/Droid views didn't marshal redraws to the UI thread. When a chart property is changed off the UI thread (e.g. from a background polling task), the native views invoked UIKit/Android draw APIs on that thread → the crash the issue describes. The MAUI view already dispatches via
Dispatcher.Dispatch; this brings the native views in line:view.BeginInvokeOnMainThread(view.InvalidateChart)view.PostInvalidate()(safe from any thread) instead ofview.Invalidate()No Core/architecture change — the platform-agnostic Core stays UI-thread-agnostic and marshaling lives in the views, matching how the MAUI view already works.
Verification
dotnet build Sources/Microcharts.slnx --configuration Release→ builds clean across Core / iOS / Droid / MAUI.Dispatcher.Dispatchmarshaling. It's a redraw-threading fix that the MAUI demo can't exercise (that path uses the already-correct MAUI view), so it's verified by compilation + parity with the MAUI approach.Closes #245.
🤖 Generated with Claude Code