我正在MS VS 2015中使用Prism 6编写一个C#WPF纯MVVM应用程序。我需要显示一个实时笛卡尔折线图,其中包含大量不断添加到系列中的点。在'A'Prism模块中,我每隔1000毫秒通过串口汇集外部设备的寄存器,并将此数据放入共享缓冲区(使用System.Threading
Timer)。
在'B'Prism模块中,我将此共享缓冲区以1000毫秒的间隔汇集(使用System.Windows.Threading.DispatcherTimer
)。 DispatcherTimer的每个刻度我从共享缓冲区获取数据,从数据创建数据点并将此数据点放到ChartValues<T>
集合中以在我的图表中投入此数据点。下面是'B'棱镜模块中的视图模型的C#代码。
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; }
}
以下是Prism UserControl中LiveCharts的XAML:
<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>
我的问题是,当我使用DispatcherTimer
每隔1000毫秒创建并添加数据点到系列时,然后(工作8-10分钟后)我的应用程序开始减速并挂出。我需要在异步模式下使用LiveCharts,以避免减速和挂起应用程序的工作。昨天我花了一整天的时间来搜索LiveCharts在异步模式下工作的例子。我曾经使用谷歌,但我找不到任何有价值的东西。
我是LiveCharts的初学者,因为我第二次只使用LiveCharts。如何让LiveCharts在异步模式下工作以避免减慢和挂起我的应用程序?为什么我的应用程序在工作7-8分钟后会变慢并挂断?我做错了什么?