2

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 :)

Tim B.
  • 88
  • 2
  • 11

1 Answers1

0

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.

Eyal Perry
  • 2,255
  • 18
  • 26