Chart: a frame can stroke a pen against a half-swapped axis pair

Open
#64 0 comments 0 reactions 1 assignee View on GitHub

@mrcsin is already working on this.

Since Sep 10, 2026.

Assessment

This issue has not been assessed yet.

Description

bug

Symptom

A pen's line can be drawn for one frame with part of its points scaled through the old Y axis and part through the new one: a step in the line, or a stretch of it outside the data area, gone on the next frame. It shows as a flicker at the moment the axis assignment changes: a pen regrouped by unit, a manual/auto scale switch, a pen added.

Not reproduced by hand yet. A drag alone does not trigger it because the Y axes do not change during a drag.

Cause

ChartAxisBinder.AssignPensToAxis (SemiPlot/SemiPlot.UI/Chart/ChartAxisBinder.cs:70) writes state.Line.Axes.YAxis = axis on the UI thread on every ApplyAxisModel, which runs after each history apply and each window change.

EnvelopeLine.Render reads Axes on Avalonia's render thread outside any lock: Axes.XAxis.Min/Max for the visible range (EnvelopeLine.cs:82) and Axes.GetPixel per point (EnvelopeLine.cs:94). Axes is ScottPlot's plain object with two reference properties; the column-buffer lock from #59 does not cover it.

A reference write is atomic, so nothing throws. A frame is not atomic: a write landing between two GetPixel calls leaves that frame drawn against two axes.

Fix options

  1. Render snapshots Axes.XAxis and Axes.YAxis into locals once at the top and uses them for the whole frame. No lock, no UI-thread blocking; one frame sees one consistent pair. Smallest change.
  2. Route the assignment through a method on EnvelopeLine that takes the existing _columnsLock, and read Axes under the same lock in Render. Consistent with #59 but blocks the UI thread for nothing the snapshot does not already give.

Option 1 is enough.

Related

TrendChartViewModel.RemovePen (TrendChartViewModel.cs:248) calls Plot.Remove(state.Line), which mutates ScottPlot's PlottableList while the render thread enumerates it with foreach: InvalidOperationException (collection modified) if it ever runs during a frame. Latent today because RemovePen has no production caller and AddPen runs once at startup before the window is shown. Decide with the behaviour/UX round: delete the method with its tests, or reimplement pen removal through IsVisible rather than Plot.Remove.

Provenance

Found during the review of #63. Present on master since the culled polyline plottable (013f491, #57).

Dominant language
C#
Stars
0
Forks
0
Avg merge
18m
Merged PRs (30d)
42

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Semiteq/SemiPlot

All issues in Semiteq/SemiPlot

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.