I have got an question about adding points to charts.
My windows forms application is using a thread to get the Y value from another server. Every 500ms I get a new value(string) which should be added as a point, but I have no idea how to do that. It would be really nice if the points will be displayed in realtime and not only after ending the process. I think it is not a real difficult question but I didn`t find a solution.
Thread:
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);
}
}
Configuration and chart
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();
Thanks for help :)
You have a classic Producer-Consumer
scenario on your hands.
Which means that one thread produces an item (the background thread)
While another consumes it (the UI thread).
One way to communicate between a producer and a consumer is with an event :
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);
}
}
}
Then, in your form you may do like so:
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
}));
}
}
Note that WinForms is single threaded, meaning that no thread can do work directly on a UI element, unless it is the UI thread.
This is why I called the Invoke
method - it simply offloads work to be carried out on the UI thread.