0

我正在尝试绘制传感器数据的实时绘图。UI 由图表、开始和停止按钮组成。

当按下开始按钮时,来自传感器的数据会使用 100 毫秒的计时器绘制在图表上。但它会引发类似系统执行引擎异常的异常。如果我用 while(true) 循环替换更新值的计时器方式,则没有例外或其他问题。但在这种情况下,我将失去对 UI 其他部分的控制,因为我只使用 1 个线程。

欢迎提出建议/意见/帮助!

while (true) 
{ 
    chart1.Series[0].Points.Clear(); 
    // Get data from sensor using sensor sdk, 
    // The function returns 2 arrays, x-array and y-array of values to be plotted 
    // Display x and z values 
    chart1.Series[0].Points.DataBindXY(adValueX, adValueZ); 
    chart1.Update(); 
    System.Threading.Thread.Sleep(100); 
}
4

2 回答 2

0

在您的 UI 线程中使用while (true)时,您基本上会阻止所有其他与 UI 相关的功能(因为 UI 线程很忙)。

有3种常见的方法来克服这个问题:

  • 使用 asyc/await :虽然我不会在你的场景中推荐它。
  • 添加Application.DoEvents()到您的循环中,这实际上是一种克服 UI 响应能力的技巧。
  • 使用计时器

您已经使用了最后一个选项,但遇到了错误。很可能您的 Timer 没有在 UI 线程上运行,这可能会在更新 UI 组件时导致问题。

有多种方法可以解决它:这是一种:

protected void OnYourTimerEventHandler()
{
    BeginInvoke(new MethodInvoker(delegate 
    {
        chart1.Series[0].Points.Clear(); 
        // Get data from sensor using sensor sdk, 
        // The function returns 2 arrays, x-array and y-array of values to be plotted 
        // Display x and z values 
        chart1.Series[0].Points.DataBindXY(adValueX, adValueZ); 
        chart1.Update(); 
    }));
}

更多文档可以在MSDN上找到

于 2020-07-20T08:13:21.300 回答
0

根据您的描述,您希望使用 100ms 的计时器并避免在使用上述代码时锁定控件。

我建议你可以使用计时器来做到这一点。

这是您可以参考的代码示例。

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Dictionary<double, double> dic = new Dictionary<double, double>();
        private void Form1_Load(object sender, EventArgs e)
        {
            chart1.Series.Clear();
            var series1 = new System.Windows.Forms.DataVisualization.Charting.Series
            {
                Name = "Series1",
                Color = System.Drawing.Color.Green,
                IsVisibleInLegend = false,
                IsXValueIndexed = true,
                ChartType = SeriesChartType.Line
            };

            this.chart1.Series.Add(series1);
            series1.Points.AddXY(1, 10);
            series1.Points.AddXY(2, 14);
            chart1.Invalidate();
            timer1.Interval = 100;
            dic.Add(1, 20);
            dic.Add(2, 30);
            dic.Add(3, 40);
            dic.Add(4, 60);
            dic.Add(5, 70);

        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            chart1.Series[0].Points.Clear();
            // Get data from sensor using sensor sdk, 
            // The function returns 2 arrays, x-array and y-array of values to be plotted 
            // Display x and z values 
            chart1.Series[0].Points.DataBindXY(dic.Keys, dic.Values);
            chart1.Update();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }
    }

结果:

在此处输入图像描述

于 2020-07-21T03:06:59.330 回答