首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Control.Invoke和Delegates绘制串口数据的延迟

使用Control.Invoke和Delegates绘制串口数据的延迟
EN

Stack Overflow用户
提问于 2014-05-03 20:56:27
回答 1查看 720关注 0票数 1

我正在从串口读取数据值,并使用调用和委托在zedgraph控件上实时绘制数据。我想点击一个断开按钮,这将停止绘图,当一个连接按钮被按下,绘图将继续。我的问题是当我重新连接时,绘图将不会以每秒1点的速度显示。会有意想不到的行为,有时包括延迟,不会规划2秒,下一秒,它将绘制2分在同一时间。有时它不会绘制3秒和下一个秒,它会同时绘制3分,有时它会很好地绘制1分每秒。有时,它会以每秒两次或三次的速度进行绘制。只有当我断开连接,然后重新连接时,才会出现此问题。我的GUI响应也开始变得更糟,每次我断开和重新连接,直到最后没有响应。

当我单击“断开”时,我会清除zedgraph,但不要关闭串行端口。当我再次单击connect时,串口将再次开始发送数据并继续绘制,每次在zedgraph上绘制新的数据点时调用control.invoke。是否我调用了太多次调用的问题,以及如何解决这个问题?我需要实时绘制,所以每次我收到一个数据点时,立即将它绘制在zedgraph上。

下面是我如何连接到串口的方法:

代码语言:javascript
复制
private void btnConnect_Click_1(object sender, EventArgs e)
    {
        curveUSB = myPaneUSB.AddCurve("Load", listUSB, Color.Black, SymbolType.Circle);
        isConnected = true;

        DateTime startTime = DateTime.Now;
        txtStartTime.Text = startTime.ToString();
        sw.Start();
        createCSVFile(startTime);

        try
        {
            if (!serialPort1.IsOpen)
            {

                serialPort1.PortName = cmbPort.Items[cmbPort.SelectedIndex].ToString();


                //Other Serial Port Property
                serialPort1.Parity = Parity.None;
                serialPort1.StopBits = StopBits.One;
                serialPort1.DataBits = 8;
                serialPort1.BaudRate = 9600;
                //Open our serial port
                serialPort1.Open();
            }
        }
        catch(Exception ex)
        {
            MessageBox.Show(ex.Message);
        }



        Thread.Sleep(100); //Always sleep before reading
        serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceivedHandler);

        // Save the beginning time for reference
        tickStart = Environment.TickCount;  //used the calculate the time 
        setGraphAxis(myPaneUSB, zgControlUSB);
        //Disable Connect button
        btnConnect.Enabled = false;
        //Enable Disconnect button
        btnDisconnect.Enabled = true;        
    }

调用和serialPort1_DataReceivedHandler:

代码语言:javascript
复制
private void serialPort1_DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {
        if (isConnected == true)
        {
            txtUSBLoad.Invoke(new EventHandler(delegate
            {

                strRawData = serialPort1.ReadLine();

                txtUSBLoad.Text = strRawData + loadUnit;
                Display_Data(strRawData, curveUSB, listUSB, zgControlUSB);


            }));
        }
    }

显示图形的Display_Data函数:

代码语言:javascript
复制
private void Display_Data(String data, LineItem curve, IPointListEdit list, ZedGraphControl zgControl) 
    {

        ts = sw.Elapsed;
        tsBT = swBT.Elapsed;
        elapsedTime = String.Format("{0:00}:{1:00}:{2:00}",tsBT.Hours, tsBT.Minutes, tsBT.Seconds);
        elapsedTimeBT = String.Format("{0:00}:{1:00}:{2:00}", tsBT.Hours, tsBT.Minutes, tsBT.Seconds);
        txtElapsedTime.Text = elapsedTime;
        txtBTElapsedTime.Text = elapsedTimeBT;


        if (zgControl.GraphPane.CurveList.Count <= 0)                    //Make sure that the curvelist has at least one curve
            return;
        curve = zgControl.GraphPane.CurveList[0] as LineItem;            //Get the first CurveItem in the graph
        if (curve == null)
            return;
        list = curve.Points as IPointListEdit;                                  //Get the PointPairList
        if (list == null)                                                       //If this is null, it means the reference at curve.Points does not
            return;                                                             //support IPointListEdit, so we won't be able to modify it
        time = (Environment.TickCount - tickStart) / 1000.0;             //Time is measured in seconds
                                             //Get current time        
        now = DateTime.Now;
        timestamp = now.ToOADate();
        list.Add(timestamp, Convert.ToDouble(data)); 
        if(fileWriter.BaseStream != null){  //If fileWriter is open, then write to file, else don't write
            fileWriter.WriteLine(String.Format("{0:yyyy-MM-dd_HH-mm-ss}", now) + "," + data);   //writes the timestamp and data to the CSV file
        }
        if (Convert.ToDouble(data) > tempLoad)  //Checks if the current load is the maximum load
        {
            tempLoad = Convert.ToDouble(data);
            txtMaxLoad.Text = tempLoad.ToString() + " " + loadUnit;
            txtBTMaxLoad.Text = tempLoad.ToString() + " " + loadUnit;
        }
        //if ((Convert.ToDouble(data) > dblThreshold) && (emailAlerts == true)) { 
        if ((Convert.ToDouble(data) > 50) && (emailAlerts == true))
        { 
            sendEmail(Convert.ToDouble(data));
        }

        XDate dateTime = curve[0].X;                                   

        zgControl.AxisChange();                                          //changes the x-axis  
        zgControl.Invalidate();                                          //Force a redraw
    }

断开按钮:

代码语言:javascript
复制
 private void btnDisconnect_Click_1(object sender, EventArgs e)
    {
        zgControlUSB.GraphPane.CurveList.Clear();
        if (fileWriter != null)
        {
            fileWriter.Close(); 
        }
        isConnected = false;
        btnConnect.Enabled = true;
        btnDisconnect.Enabled = false;
        txtUSBLoad.Text = initText;
        DateTime endTime = DateTime.Now;
        txtEndTime.Text = endTime.ToString();   //displays the time stamp when the plotting stops
        sw.Stop();  //stops the stop watch 

    }

当我断开连接时,我不会关闭串行端口,因为当我这样做时,问题会更严重,并且我看到总是关闭并重新打开一个串行端口是不好的。相反,我使用了一个isConnected标志来启动和停止绘图。任何帮助都是非常感谢的!提前感谢!

EN

回答 1

Stack Overflow用户

发布于 2014-05-03 21:11:32

调用txtUSBLoad.Invoke()将处理切换到GUI线程(用于处理用户输入和绘制控件的同一个线程)。通过将所有处理放入调用调用()中,您实际上是在淹没GUI线程。

如果您的串行更新足够频繁,这将导致交互/重新绘制GUI的延迟。

这里有几个选项,第一件事是将所有处理保留在从串口接收消息的线程中。查看正在更新的所有可视控件,确定它们需要更新的数据,并在调用Invoke()之前处理这些数据。创建一个类来保存数据。

这可能太慢了,这意味着您将积累大量无法及时处理的串行数据。如果是这样的话,您可以将传入的数据混为一谈,如果您认为丢失更新没有问题的话。你得看看这是否适用于你的情况。

如果您想尝试并并行处理传入的数据,请查看TPL数据流中如何为数据创建处理管道的示例。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23449745

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档