Skip to content

Marshal iOS/Droid chart redraws to the UI thread; remove dead PlanifyInvalidate (#245)#381

Merged
follesoe merged 2 commits into
mainfrom
fix/245-offthread-invalidate
Jul 21, 2026
Merged

Marshal iOS/Droid chart redraws to the UI thread; remove dead PlanifyInvalidate (#245)#381
follesoe merged 2 commits into
mainfrom
fix/245-offthread-invalidate

Conversation

@follesoe

Copy link
Copy Markdown
Contributor

Summary

Addresses the two problems behind #245 ("Chart presumes properties are always changed on the UI thread; exceptions lost in async void PlanifyInvalidate").

1. PlanifyInvalidate was dead code. The async void PlanifyInvalidate method the issue called out has no call sites anywhere in the repo. Removed it (and its now-unused invalidationPlanification field).

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:

  • iOS: view.BeginInvokeOnMainThread(view.InvalidateChart)
  • Droid: view.PostInvalidate() (safe from any thread) instead of view.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.
  • The change mirrors the MAUI view's already-proven Dispatcher.Dispatch marshaling. 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

…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>
@follesoe follesoe added the bug label Jul 21, 2026
@follesoe
follesoe requested a review from Copilot July 21, 2026 11:32
@follesoe follesoe self-assigned this Jul 21, 2026
@follesoe follesoe added this to the v2.0.0 milestone Jul 21, 2026

Copilot AI left a comment

Copy link
Copy Markdown

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 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 PlanifyInvalidate method and its backing invalidationPlanification field from Chart.
  • iOS ChartView now dispatches redraws via BeginInvokeOnMainThread(...) when the chart raises Invalidated.
  • Android ChartView now uses PostInvalidate() (thread-safe) instead of Invalidate() when the chart raises Invalidated.

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.

Comment thread Sources/Microcharts.iOS/ChartView.cs Outdated
Comment thread Sources/Microcharts.Droid/ChartView.cs Outdated
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>
@follesoe
follesoe merged commit ad2fd7e into main Jul 21, 2026
2 checks passed
@follesoe
follesoe deleted the fix/245-offthread-invalidate branch July 21, 2026 12:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chart presumes that properties are always being changed on the UI thread. Exceptions are lost in async void PlanifyInvalidate.

2 participants