Zedgraph 以快速输入速率绘制实时图形
Zedgraph plotting real time graph with fast input rate
我正在使用 Zedgraph 的 RollingPointPairList 绘制实时图表。我每秒接收 100 点并尝试每秒绘制 100 点。但是 zedgraph 显示滞后并且每秒最多只能绘制 20 个点。我正在使用以下代码进行绘图
RollingPointPairList samp = new RollingPointPairList(105);
private void Form1_Load(object sender, EventArgs e)
{
CreateGraph(zg1);
SetSize();
}
int x1 = 0;
private void TimerEventProcessor(int[] diff)
{
zg1.GraphPane.XAxis.Scale.MaxAuto = true;
x1 += 1;
samp.Add(diff[0], x1);
if (samp.Count >= 100)
{
zg1.AxisChange();
zg1.Invalidate();
zg1.Refresh();
Thread.Sleep(50);
}
}
private void Form1_Resize(object sender, EventArgs e)
{
SetSize();
}
private void SetSize()
{
zg1.Location = new Point(10, 10);
zg1.Size = new Size(this.ClientRectangle.Width - 10, this.ClientRectangle.Height - 10);
}
private void CreateGraph(ZedGraphControl zgc)
{
GraphPane myPane = zgc.GraphPane;
myPane.Title.Text = "Test";
myPane.XAxis.Title.Text = "X Value";
myPane.YAxis.Title.Text = "Y Axis";
LineItem myCurve;
myCurve= myPane.AddCurve("Curve 1", samp, Color.Blue, SymbolType.Star);
myCurve.Symbol.Fill = new Fill(Color.White);
myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45F);
myPane.Fill = new Fill(Color.White, Color.FromArgb(220, 220, 255), 45F);
zgc.AxisChange();
zgc.Refresh();
}
这就是他们改进我的代码的任何方法,以便我每秒可以绘制 100 个点或更多点。
每秒绘制 100 个点远远超出 ZedGraph 的限制。我怀疑瓶颈不是 ZedGraph。为了能够尽我所能重现您的用例,我快速完成了这段代码,它通过我以与您相同的方式初始化的 ZedGraph 控件每秒抛出最大点数:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using ZedGraph;
namespace WindowsFormsApplication1 {
static class Program {
/// <summary>
/// Point d'entrée principal de l'application.
/// </summary>
[STAThread]
static void Main() {
Application.Run(new Form1());
}
class Form1 : Form {
ZedGraphControl zgc;
System.Windows.Forms.Label lbl;
public Form1() {
this.WindowState = FormWindowState.Maximized;
lbl = new System.Windows.Forms.Label { Parent = this, Dock = DockStyle.Bottom, AutoSize = false, TextAlign = ContentAlignment.MiddleCenter };
zgc = new ZedGraphControl {
Parent = this,
Dock = DockStyle.Fill,
Margin = new Padding(10)
};
var myPane = zgc.GraphPane;
myPane.Title.Text = "Test";
myPane.XAxis.Title.Text = "X Value";
myPane.YAxis.Title.Text = "Y Axis";
myPane.XAxis.Scale.MaxAuto = true;
var myCurve = myPane.AddCurve("Curve 1", samp, Color.Blue, SymbolType.Star);
myCurve.Symbol.Fill = new Fill(Color.White);
myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45F);
myPane.Fill = new Fill(Color.White, Color.FromArgb(220, 220, 255), 45F);
}
RollingPointPairList samp = new RollingPointPairList(105);
int c;
CancellationTokenSource cts = new CancellationTokenSource();
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
var t = new System.Timers.Timer { Interval = 1000 };
t.Elapsed += (sender, eventargs) => { this.BeginInvoke(new Action(() => { lbl.Text = "Dot per seconds: " + c.ToString(); c = 0; })); };
t.Start();
Task.Run(() => {
var r = new Random();
while(!cts.IsCancellationRequested) {
TimerEventProcessor(r.Next(-10, 10));
};
});
}
protected override void OnClosing(CancelEventArgs e) {
cts.Cancel();
cts.Token.WaitHandle.WaitOne();
base.OnClosing(e);
}
int x1 = 0;
void TimerEventProcessor(int d) {
x1++; c++;
samp.Add(d, x1);
zgc.AxisChange();
zgc.Invalidate();
}
}
}
}
如果我错误地假设您的代码应该如何 运行,请告诉我。但是,它 运行 在我的机器上没问题。
恕我直言,当有人在我的团队中使用 ZedGraph 时,我给出的建议是:
- 不要多次调用 Invalidate 方法。 (您的代码使用 Invalidate,然后 Refresh。当 Refresh 执行无效时,您的代码执行两次)
- AxisChange 方法仅在使用自动缩放时才有用(您的代码对此没问题)
- 不在 UI 线程上执行 CPU 密集处理。
我怀疑最后一点是造成瓶颈的原因:接收数据包可以在单独的线程上更好地实现,该线程使用 windows Forms SynchronizationContext 在 ZedGraph 控件上调用 Invalidate。
我正在使用 Zedgraph 的 RollingPointPairList 绘制实时图表。我每秒接收 100 点并尝试每秒绘制 100 点。但是 zedgraph 显示滞后并且每秒最多只能绘制 20 个点。我正在使用以下代码进行绘图
RollingPointPairList samp = new RollingPointPairList(105);
private void Form1_Load(object sender, EventArgs e)
{
CreateGraph(zg1);
SetSize();
}
int x1 = 0;
private void TimerEventProcessor(int[] diff)
{
zg1.GraphPane.XAxis.Scale.MaxAuto = true;
x1 += 1;
samp.Add(diff[0], x1);
if (samp.Count >= 100)
{
zg1.AxisChange();
zg1.Invalidate();
zg1.Refresh();
Thread.Sleep(50);
}
}
private void Form1_Resize(object sender, EventArgs e)
{
SetSize();
}
private void SetSize()
{
zg1.Location = new Point(10, 10);
zg1.Size = new Size(this.ClientRectangle.Width - 10, this.ClientRectangle.Height - 10);
}
private void CreateGraph(ZedGraphControl zgc)
{
GraphPane myPane = zgc.GraphPane;
myPane.Title.Text = "Test";
myPane.XAxis.Title.Text = "X Value";
myPane.YAxis.Title.Text = "Y Axis";
LineItem myCurve;
myCurve= myPane.AddCurve("Curve 1", samp, Color.Blue, SymbolType.Star);
myCurve.Symbol.Fill = new Fill(Color.White);
myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45F);
myPane.Fill = new Fill(Color.White, Color.FromArgb(220, 220, 255), 45F);
zgc.AxisChange();
zgc.Refresh();
}
这就是他们改进我的代码的任何方法,以便我每秒可以绘制 100 个点或更多点。
每秒绘制 100 个点远远超出 ZedGraph 的限制。我怀疑瓶颈不是 ZedGraph。为了能够尽我所能重现您的用例,我快速完成了这段代码,它通过我以与您相同的方式初始化的 ZedGraph 控件每秒抛出最大点数:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using ZedGraph;
namespace WindowsFormsApplication1 {
static class Program {
/// <summary>
/// Point d'entrée principal de l'application.
/// </summary>
[STAThread]
static void Main() {
Application.Run(new Form1());
}
class Form1 : Form {
ZedGraphControl zgc;
System.Windows.Forms.Label lbl;
public Form1() {
this.WindowState = FormWindowState.Maximized;
lbl = new System.Windows.Forms.Label { Parent = this, Dock = DockStyle.Bottom, AutoSize = false, TextAlign = ContentAlignment.MiddleCenter };
zgc = new ZedGraphControl {
Parent = this,
Dock = DockStyle.Fill,
Margin = new Padding(10)
};
var myPane = zgc.GraphPane;
myPane.Title.Text = "Test";
myPane.XAxis.Title.Text = "X Value";
myPane.YAxis.Title.Text = "Y Axis";
myPane.XAxis.Scale.MaxAuto = true;
var myCurve = myPane.AddCurve("Curve 1", samp, Color.Blue, SymbolType.Star);
myCurve.Symbol.Fill = new Fill(Color.White);
myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45F);
myPane.Fill = new Fill(Color.White, Color.FromArgb(220, 220, 255), 45F);
}
RollingPointPairList samp = new RollingPointPairList(105);
int c;
CancellationTokenSource cts = new CancellationTokenSource();
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
var t = new System.Timers.Timer { Interval = 1000 };
t.Elapsed += (sender, eventargs) => { this.BeginInvoke(new Action(() => { lbl.Text = "Dot per seconds: " + c.ToString(); c = 0; })); };
t.Start();
Task.Run(() => {
var r = new Random();
while(!cts.IsCancellationRequested) {
TimerEventProcessor(r.Next(-10, 10));
};
});
}
protected override void OnClosing(CancelEventArgs e) {
cts.Cancel();
cts.Token.WaitHandle.WaitOne();
base.OnClosing(e);
}
int x1 = 0;
void TimerEventProcessor(int d) {
x1++; c++;
samp.Add(d, x1);
zgc.AxisChange();
zgc.Invalidate();
}
}
}
}
如果我错误地假设您的代码应该如何 运行,请告诉我。但是,它 运行 在我的机器上没问题。
恕我直言,当有人在我的团队中使用 ZedGraph 时,我给出的建议是:
- 不要多次调用 Invalidate 方法。 (您的代码使用 Invalidate,然后 Refresh。当 Refresh 执行无效时,您的代码执行两次)
- AxisChange 方法仅在使用自动缩放时才有用(您的代码对此没问题)
- 不在 UI 线程上执行 CPU 密集处理。
我怀疑最后一点是造成瓶颈的原因:接收数据包可以在单独的线程上更好地实现,该线程使用 windows Forms SynchronizationContext 在 ZedGraph 控件上调用 Invalidate。