как временно приостановить обновление графиков данных в реальном времени - PullRequest
0 голосов
/ 28 сентября 2018

Мне бы хотелось, чтобы «Приостановить» обновления серии графика выполнило определенную работу (например, если у меня есть кнопка, при ее нажатии будет приостановлено обновление графика, а затем при нажатии кнопки возобновления обновятся все точки приостановки в серии.

Я знаю о

chart1.Series.SuspendUpdates();

, но, похоже, он не работает со мной. Я использую образец mschart - данные в реальном времени (потокобезопасные).

Вотполный код

public partial class RealTimeSample : Form
{
    public RealTimeSample()
    {
        InitializeComponent();
    }
    private Thread addDataRunner;
    private Random rand = new Random();

    public delegate void AddDataDelegate();
    public AddDataDelegate addDataDel;
    private void RealTimeSample_Load(object sender, System.EventArgs e)
    {

        // create the Adding Data Thread but do not start until start button clicked
        ThreadStart addDataThreadStart = new ThreadStart(AddDataThreadLoop);
        addDataRunner = new Thread(addDataThreadStart);

        // create a delegate for adding data
        addDataDel += new AddDataDelegate(AddData);

    }



    /// Main loop for the thread that adds data to the chart.
    /// The main purpose of this function is to Invoke AddData
    /// function every 1000ms (1 second).
    private void AddDataThreadLoop()
    {
        while (true)
        {
            chart1.Invoke(addDataDel);

            Thread.Sleep(1000);
        }
    }

    public void AddData()
    {
        DateTime timeStamp = DateTime.Now;

        foreach (Series ptSeries in chart1.Series)
        {
            AddNewPoint(timeStamp, ptSeries);
        }
    }

    /// The AddNewPoint function is called for each series in the chart when
    /// new points need to be added.  The new point will be placed at specified
    /// X axis (Date/Time) position with a Y value in a range +/- 1 from the previous
    /// data point's Y value, and not smaller than zero.
    public void AddNewPoint(DateTime timeStamp, System.Windows.Forms.DataVisualization.Charting.Series ptSeries)
    {
        double newVal = 0;

        if (ptSeries.Points.Count > 0)
        {
            newVal = ptSeries.Points[ptSeries.Points.Count - 1].YValues[0] + ((rand.NextDouble() * 2) - 1);
        }

        if (newVal < 0)
            newVal = 0;

        // Add new data point to its series.
        chart1.Series.SuspendUpdates();
        ptSeries.Points.AddXY(timeStamp.ToOADate(), rand.Next(10, 20));
        chart1.Series.SuspendUpdates();
        // remove all points from the source series older than 1.5 minutes.
        double removeBefore = timeStamp.AddSeconds((double)(90) * (-1)).ToOADate();
        //remove oldest values to maintain a constant number of data points
        while (ptSeries.Points[0].XValue < removeBefore)
        {
            ptSeries.Points.RemoveAt(0);
        }

        chart1.ChartAreas[0].AxisX.Minimum = ptSeries.Points[0].XValue;
        chart1.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries.Points[0].XValue).AddMinutes(2).ToOADate();


    }

    /// Clean up any resources being used.
    protected override void Dispose(bool disposing)
    {
        if ((addDataRunner.ThreadState & ThreadState.Suspended) == ThreadState.Suspended)
        {
            addDataRunner.Resume();
        }
        addDataRunner.Abort();

        if (disposing)
        {
            if (components != null)
            {
                components.Dispose();
            }
        }
        base.Dispose(disposing);
    }

    private void startTrending_Click_1(object sender, EventArgs e)
    {
        // Disable all controls on the form
        startTrending.Enabled = false;
        // and only Enable the Stop button
        stopTrending.Enabled = true;

        // Predefine the viewing area of the chart
        var minValue = DateTime.Now;
        var maxValue = minValue.AddSeconds(120);

        chart1.ChartAreas[0].AxisX.Minimum = minValue.ToOADate();
        chart1.ChartAreas[0].AxisX.Maximum = maxValue.ToOADate();

        // Reset number of series in the chart.
        chart1.Series.Clear();

        // create a line chart series
        Series newSeries = new Series("Series1");
        newSeries.ChartType = SeriesChartType.Line;
        newSeries.BorderWidth = 2;
        newSeries.Color = Color.OrangeRed;
        newSeries.XValueType = ChartValueType.DateTime;
        chart1.Series.Add(newSeries);

        // start worker threads.
        if (addDataRunner.IsAlive == true)
        {
            addDataRunner.Resume();
        }
        else
        {
            addDataRunner.Start();
        }
    }


    private void stopTrending_Click_1(object sender, EventArgs e)
    {
        if (addDataRunner.IsAlive == true)
        {
            addDataRunner.Suspend();
        }

        // Enable all controls on the form
        startTrending.Enabled = true;
        // and only Disable the Stop button
        stopTrending.Enabled = false;
    }        
}

РЕДАКТИРОВАТЬ:

Я понял, что, пока вы установите минимальное или максимальное свойство для оси, график будет отображаться, даже есливы использовали

chart1.Series.SuspendUpdates();

Мне пришлось удалить эти линии после того, как я позвонил SuspendUpdates(), и теперь я могу видеть приостановленную серию графиков

chart1.ChartAreas[0].AxisX.Minimum = ptSeries.Points[0].XValue;
chart1.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries.Points[0].XValue).AddMinutes(2).ToOADate();

1 Ответ

0 голосов
/ 29 сентября 2018

MsChart поддерживает это напрямую, и действительно, использование Series.SuspendUpdates() - хороший способ, но вы должны сделать это правильно.(Однако недостаток см. В приведенном ниже обновлении)

MSDN говорит об этом:

Вызов метода Invalidate не будет иметьэффект после вызова метода SuspendUpdates.

Если вы вызываете метод SuspendUpdates несколько раз, вам потребуется вызвать метод ResumeUpdates , равный числу раз.

Это объясняет, почему это не работает для вас: сохранение вызовов сбалансированным имеет решающее значение.Вы должны следить за ними самостоятельно, так как нет счетчика, который вы могли бы запросить.Но если вы отклоните вызовы ResumeUpdates, ничего плохого не произойдет, дополнительные вызовы просто игнорируются, а следующий SuspendUpdates снова приостановится.

Вот пример снимка экрана, посмотрите счетчик приостановки ..!

enter image description here

Обратите внимание, что обычно добавление точек автоматически вызывает Invalidate.Если вы занимаетесь другими вещами, такими как рисование в событии Paint и т. Д., Вам может потребоваться позвонить Chart.Invalidate(), что SuspendUpdates предотвратит, пока не будет отменено с тем же номером ResumeUpdates ..


В качестве альтернативы вы также можете использовать один из следующих простых способов:

  • Самый простой способ - создать DataPoints через конструктор, а затем либо
    • использовать series.Add(theNewPoint)для обычный или ..
    • используйте someList<DataPoint>.Add(theNewPoint) для режим паузы .

При установке наВ режиме паузы просто добавьте все точки к series.Points перед его очисткой.К сожалению, points.AddRange нет, поэтому вам придется использовать цикл foreach.Может быть, chart.SuspendLayout может помочь с производительностью.

  • Другой обходной путь, который приходит на ум, может подходить или не подходить: вы можете играть с xAxis.Maximum и, возможно, xAxis.Minimum values.Установив для них фиксированные значения, вы позволите добавлять точки справа, не отображая их.Чтобы показать весь набор точек, вы должны сбросить их на double.NaN.Это может работать для вас, но может также мешать тому, что у вас есть.

Обновление: Как отметил OP, данные обновляются, когда он изменяет Minimum и /или Maximum из Axis.Этот же эффект будет проявляться во многих других случаях:

  • Вызов chart.AreasRecalculateAxesScale();
  • Изменение Size
  • Изменение оси любой свойство типа Color или Width ..
  • Изменение LegendText из Series
  • и многие другие ..

Так что я думаюобновленные данные необходимы всякий раз, когда ChartArea манипулируют и вынуждены обновлять себя.

Таким образом, это может сделать первый обходной путь лучше, потому что более надежное решение .

...