I am writing a C# WPF pure MVVM application using Prism 6 in MS VS 2015. I need to display a real-time Cartesian line chart with large amount of points which are continuously added to series. In 'A' Prism module I pool the register of the external device through the serial port every 1000 milliseconds and put this data in shared buffer (using System.Threading
Timer for it).
In 'B' Prism module I pool this shared buffer with an interval of 1000 milliseconds (using System.Windows.Threading.DispatcherTimer
for it). Each tick of the DispatcherTimer I take data from shared buffer, create the data-point from the data and put this data-point to ChartValues<T>
collection to drow this data-point in my chart. Below is the C# code of View Model in 'B' Prism module where I do it.
public class DeviceReadingViewModel : BindableBase, IConfirmNavigationRequest
{
/// <summary>
/// Coordinates for chart's data-point.
/// </summary>
public class ChartPoint
{
/// <summary>
/// X axis value.
/// </summary>
public DateTime X;
/// <summary>
/// Y axis value.
/// </summary>
public double Y;
}
// X-axis maximum.
private double _axisMax;
public double AxisMax
{
get { return this._axisMax; }
set { this.SetProperty(ref this._axisMax, value); }
}
// X-axis minimum
private double _axisMin;
public double AxisMin
{
get { return this._axisMin; }
set { this.SetProperty(ref this._axisMin, value); }
}
// Constructor
public DeviceReadingViewModel()
{
// Use DateTime values for X-axis, and values from outer device register for Y-axis.
var mapper = Mappers.Xy<ChartPoint>().X(model => model.X.Ticks).Y(model => model.Y);
// Save the mapper.
Charting.For<ChartPoint>(mapper);
// Chart's data-point collection.
Values = new ChartValues<ChartPoint>();
// Set format for X.
DateTimeFormatter = value => new DateTime(DateTime.Now.Ticks).ToString("hh:mm:ss");
// Set unit interval on X-axis as 2 seconds.
AxisStep = TimeSpan.FromSeconds(2).Ticks;
// Initialize System.Windows.Threading.DispatcherTimer.
this.Timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(1000) };
this.Timer.Tick += Timer_Tick;
}
// Timer tick handler.
private void Timer_Tick(object sender, EventArgs e)
{
// Create new data-point for chart.
ChartPoint chartData = new ChartPoint();
chartData.X = DateTime.Now;
// Here GlobalStaticMembers.GasVelocityBuffer is shared buffer comprising new value from outer device register.
chartData.Y = GlobalStaticMembers.GasVelocityBuffer;
// Set minimum and maximum on X-axis:
if (AxisMin == 0 && AxisMax == 0)
{
// This operation is performed once.
AxisMax = chartData.X.Ticks + TimeSpan.FromSeconds(60).Ticks;
AxisMin = chartData.X.Ticks;
}
else
{
if (this.Values.Count >= 60)
{
// And this operation is performed every second, after the number of points to exceed 60 points.
this.AxisMin = this.AxisMin + TimeSpan.FromSeconds(1).Ticks;
this.AxisMax = this.AxisMax + TimeSpan.FromSeconds(1).Ticks;
}
}
// Draw data-point in the chart.
this.Values.Add(chartData);
}
// Timer to pool shared buffer.
public DispatcherTimer Timer { get; set; }
// X-axis value formatter.
public Func<double, string> DateTimeFormatter { get; set; }
// The price of the unit interval.
public double AxisStep { get; set; }
// Chart data-point colection.
public ChartValues<ChartPoint> Values { get; set; }
}
Below is XAML of LiveCharts in Prism UserControl:
<lvc:CartesianChart Grid.Row="0" Grid.Column="0">
<lvc:CartesianChart.Series>
<lvc:LineSeries Values="{Binding Values}" PointGeometrySize="10" StrokeThickness="2"/>
</lvc:CartesianChart.Series>
<lvc:CartesianChart.AxisX>
<lvc:Axis LabelFormatter="{Binding DateTimeFormatter}" MaxValue="{Binding AxisMax}" MinValue="{Binding AxisMin}" DisableAnimations="True">
<lvc:Axis.Separator>
<lvc:Separator Step="{Binding AxisStep}"/>
</lvc:Axis.Separator>
</lvc:Axis>
</lvc:CartesianChart.AxisX>
</lvc:CartesianChart>
My problem is that when I create and add data-point to series every 1000 milliseconds using DispatcherTimer
then (after 8 - 10 minutes of work) my application begins to slow down and hang out. I'm in need of working of LiveCharts in asynchronous mode to avoid slowdowns and hanging up in the application's work. Yesterday I spent the whole day in search of examples where LiveCharts works in asynchronous mode. I had used Google for it but I did not find anything worthwhile.
I'm beginner in LiveCharts because I work with the LiveCharts only the second time. How to get the LiveCharts to work in asynchronous mode in order to avoid slowdowns and hanging up of my application? Why does my application slow down and hang up after 7-8 minutes of work? What I'm doing wrong?