首页 > 解决方案 > C# WinForm ChartControl 有时实时显示为零

问题描述

我有一个从 PLC 读取值的应用程序,并使用 thouse 值每秒绘制图表,每 45 秒将日期记录到 MySQL 数据库。到目前为止它工作正常,但是当我对其进行测试时,我意识到它有时会读取错误的值,即 0。例如,PLC 值始终为 45,但我一次又一次地看到我的图表绘制 0 值。我的图表每 1000 毫秒绘制一次,我尝试将其增加到 2000 但它仍然相同。当我尝试打开另一个应用程序(例如 Windows 资源管理器)时,我意识到会发生这种情况。我要在 13 个不同的图表控件上读取和绘制 13 个值。以下是我用来获取值并仅为一个 PLC 值和图表控件绘制图表的代码。一世

数据点类:

public class DataPoint
        {
            public DateTime Argument { get; set; }
            public double Value { get; set; }
            public DataPoint(DateTime argument, double value)
            {
                Argument = argument;
                Value = value;
            }
        }

表单加载事件

            System.Drawing.Font myfont = new System.Drawing.Font("Microsoft Sans Serif", 20);
            System.Drawing.Font baslikFont = new System.Drawing.Font("Microsoft YaHei", 20,System.Drawing.FontStyle.Bold);
            
            //tb1
            tb1.Titles.Add(new ChartTitle { Text = basliklar[1],Font=baslikFont,TextColor=System.Drawing.Color.DeepSkyBlue });
            Series s1 = new Series();
            s1.ChangeView(ViewType.Spline);
            s1.DataSource = dp1;
            s1.DataSourceSorted = true;
            s1.ArgumentDataMember = "Argument";
            s1.ValueDataMembers.AddRange("Value");
            tb1.Series.Add(s1);
            LineSeriesView sv1 = (LineSeriesView)s1.View;
            sv1.LastPoint.LabelDisplayMode = SidePointDisplayMode.DiagramEdge;
            sv1.LastPoint.Label.TextPattern = "{V:f2}";
            sv1.LastPoint.Label.Font = myfont;

            XYDiagram dg1 = (XYDiagram)tb1.Diagram;
            dg1.AxisX.DateTimeScaleOptions.ScaleMode = ScaleMode.Continuous;
            dg1.AxisX.Label.ResolveOverlappingOptions.AllowRotate = false;
            dg1.AxisX.Label.ResolveOverlappingOptions.AllowStagger = false;
            dg1.AxisX.WholeRange.SideMarginsValue = 0;
            dg1.AxisY.ConstantLines.Add(new ConstantLine("Alt limit", altlimit[1]));
            dg1.AxisY.ConstantLines.Add(new ConstantLine("Üst limit", ustlimit[1]));
            dg1.AxisY.ConstantLines[0].Color = System.Drawing.Color.Red;
            dg1.AxisY.ConstantLines[1].Color = System.Drawing.Color.Red;
            dg1.DependentAxesYRange = DefaultBoolean.True;
            dg1.AxisY.WholeRange.AlwaysShowZeroLevel = false;

            timer = new System.Threading.Timer(_ => Timer_Tick(), null, 0, 1000);
            timer2 = new System.Threading.Timer(_ => Timer1_Tick(), null, 45000, 45000);

从 PLC 读取设定值

        try
            {
                atolyevals = atolye.ReadHoldingRegisters(2001, 32);
                if (a_s != null)
                {
                    a_s = null;
                    lineAdd(simdi() + " Atölye PLC bağlantısı sağlandı","g");
                }
            }
        catch
       {
          //Error checking methods
        }

       //Adding new point to the Chart Control
        dp1.Add(new DataPoint(DateTime.Now, gazatolyevals[0]));
                if (dp1.Count > ViewportPointCount)
                    dp1.RemoveAt(0); //if out of viewport remove the first entrance

标签: c#chartstimerdevexpressmodbus

解决方案


您正在使用System.Threading.Timer我认为会触发您的阅读代码的。问题是这个计时器在后台线程上运行,而您正在从这个线程更新 UI。这是不允许的,可能会导致各种问题。UI 对象只允许从 UI 线程更改。

解决方案是使用诸如 winforms 计时器之类的东西在 UI 线程上运行读取代码,或者使用例如Control.BeginInvoke将 UI 更新部分发布到主线程。


推荐阅读