Reputation: 1552
ScottPlot is used to display a real time chart with 10'000+ data points.
Datapoints are added every seconds, so the chart needs to be updated.
A timer perform the refresh every seconds, however, it freezes the whole UI for a few ms, which is annying.
ScottPlot does have a Chart.RenderRequest();
method which is non-blocking, but the chart is still rendered on the UI thread so that does not solve the issue.
And of course, if we try to refresh it from a background worker, a thread exception happens.
var bg = new BackgroundWorker();
bg.DoWork += (s, e) =>
{
Chart.RenderRequest();
};
bg.RunWorkerAsync();
Is there any ways to render the chart in a separate thread with WPF and ScottPlot ?
Edit:
Did timing analysis, Refresh, Render, RefreshRequest, RenderRequest all have similar execution time, despite the "request" are supposedly non-blocking.
Upvotes: 0
Views: 2381
Reputation: 27
Some time ago I faced a similar issue.
I had a lot of data to be displayed in multiple charts, I found that (in my canse) an acceptable limit to have a satisfying user experience is to limit the data rendered by scottplot to about 1 million points. Here there are some tips that maybe can help you to solve your issue.
If you can, use SignalXY plot. It is designed to render a lot of data, so the rendering is much faster than using any other type of graph.
Unfortunately you must render the graph in the UI thread, but you can limit the use of the UI thread to the call wpfPlot.Refresh(). Create one pair of double array double[] Ys and Xs[] of the maximum size that your data can have. Create a plot of the desired type and keep the instance in your class as a class variable (same thing for the other plottables elements, like crosshair or legend). When you need to update data just change the value of Ys and Xs. Do not add and remove the plots from scottplot wpfPlot.
I write a small example below, just to give you an idea:
double[] times;
double[] values;
SignalXY plot;
private void Initialize()
{
wpfPlot.Plot.Clear(); //This removes all plottables
times = new double[MaxSamples];
values = new double[MaxSamples];
plot = wpfPlot.Plot.AddSignalXY(times,values);
}
private void UpdatePlot()
{
int counter=0;
foreach(var data in myData)
{
times[counter] = data.Time;
values[Counter = data.Value;
counter++;
}
//This tells to scottplot to render only until the index counter, so you
//can have a bigger Xs arrays that can be created only at the beginning
plot.MaxRenderIndex=counter;
//This call must be done in UI thread
wpfPlot.Refresh();
}
These are the two changes that, for me, improved the rendering performances by A LOT. Hope that can be useful for you too.
Upvotes: 0