C#实时给Chart加点
C# Adding points to Chart in realtime
我有一个关于向图表添加点的问题。
我的 windows 表单应用程序正在使用线程从另一台服务器获取 Y 值。每 500 毫秒我都会得到一个新值(字符串),应该将其添加为一个点,但我不知道该怎么做。如果这些点将实时显示而不是仅在结束过程后显示,那就太好了。
我认为这不是一个真正困难的问题,但我没有找到解决方案。
主题:
private void Work()
{
int counter = 0;
while (true)
{
counter++;
WebClient code = new WebClient();
speed_str = code.DownloadString("http://192.168.19.41/speedfile.html");
speedval = Convert.ToDouble(speed_str);
Console.WriteLine(speedval.ToString() + "\n Times executed: " + counter);
Thread.Sleep(1000);
}
}
配置和图表
Thread thread = new Thread(new ThreadStart(this.Work));
thread.IsBackground = true;
thread.Name = "My Worker.";
thread.Start();
//Speed
Series speed = new Series("Speed[m/s]");
speed.ChartType = SeriesChartType.Spline;
//Engines Left
engleft = new Series("Engines Left");
engleft.ChartType = SeriesChartType.Spline;
Engines.Series.Add(engleft);
engleft.Points.Clear();
string speed_read = Console.ReadLine();
感谢您的帮助:)
你手上有一个经典的Producer-Consumer
场景。
这意味着一个线程产生一个项目(后台线程)
而另一个消耗它(UI 线程)。
生产者和消费者之间进行通信的一种方式是使用事件:
class Producer
{
public event EventHandler<double> YSeriesEvent;
private Thread thread;
public Producer()
{
thread = new Thread(new ThreadStart(this.Work));
thread.IsBackground = true;
thread.Name = "My Worker.";
}
public void Start()
{
thread.Start();
}
private void Work()
{
int counter = 0;
while (true)
{
counter++;
WebClient code = new WebClient();
speed_str = code.DownloadString("http://192.168.19.41/speedfile.html");
speedval = Convert.ToDouble(speed_str);
YSeriesEvent?.Invoke(this, speedval);
}
}
}
然后,在您的表单中,您可以这样做:
class MyForm : Form
{
private Producer producer;
public MyForm()
{
producer = new Producer();
producer.YSeriesEvent += MyHandler ;
Load+= (sender, args) => producer.Start();
}
private void MyHandler(object o, double val)
{
Invoke(new Action(() =>
{
//add value to chart here
}));
}
}
请注意,WinForms 是单线程的,这意味着没有线程可以直接在 UI 元素上工作,除非它是 UI 线程。
这就是我调用 Invoke
方法的原因 - 它只是卸载要在 UI 线程上执行的工作。
我有一个关于向图表添加点的问题。
我的 windows 表单应用程序正在使用线程从另一台服务器获取 Y 值。每 500 毫秒我都会得到一个新值(字符串),应该将其添加为一个点,但我不知道该怎么做。如果这些点将实时显示而不是仅在结束过程后显示,那就太好了。 我认为这不是一个真正困难的问题,但我没有找到解决方案。
主题:
private void Work()
{
int counter = 0;
while (true)
{
counter++;
WebClient code = new WebClient();
speed_str = code.DownloadString("http://192.168.19.41/speedfile.html");
speedval = Convert.ToDouble(speed_str);
Console.WriteLine(speedval.ToString() + "\n Times executed: " + counter);
Thread.Sleep(1000);
}
}
配置和图表
Thread thread = new Thread(new ThreadStart(this.Work));
thread.IsBackground = true;
thread.Name = "My Worker.";
thread.Start();
//Speed
Series speed = new Series("Speed[m/s]");
speed.ChartType = SeriesChartType.Spline;
//Engines Left
engleft = new Series("Engines Left");
engleft.ChartType = SeriesChartType.Spline;
Engines.Series.Add(engleft);
engleft.Points.Clear();
string speed_read = Console.ReadLine();
感谢您的帮助:)
你手上有一个经典的Producer-Consumer
场景。
这意味着一个线程产生一个项目(后台线程)
而另一个消耗它(UI 线程)。
生产者和消费者之间进行通信的一种方式是使用事件:
class Producer
{
public event EventHandler<double> YSeriesEvent;
private Thread thread;
public Producer()
{
thread = new Thread(new ThreadStart(this.Work));
thread.IsBackground = true;
thread.Name = "My Worker.";
}
public void Start()
{
thread.Start();
}
private void Work()
{
int counter = 0;
while (true)
{
counter++;
WebClient code = new WebClient();
speed_str = code.DownloadString("http://192.168.19.41/speedfile.html");
speedval = Convert.ToDouble(speed_str);
YSeriesEvent?.Invoke(this, speedval);
}
}
}
然后,在您的表单中,您可以这样做:
class MyForm : Form
{
private Producer producer;
public MyForm()
{
producer = new Producer();
producer.YSeriesEvent += MyHandler ;
Load+= (sender, args) => producer.Start();
}
private void MyHandler(object o, double val)
{
Invoke(new Action(() =>
{
//add value to chart here
}));
}
}
请注意,WinForms 是单线程的,这意味着没有线程可以直接在 UI 元素上工作,除非它是 UI 线程。
这就是我调用 Invoke
方法的原因 - 它只是卸载要在 UI 线程上执行的工作。