串行数据接收使应用程序冻结

时间:2018-02-13 06:44:20

标签: c#

我正在开发一个Windows表单应用程序,我通过按钮发送数据,并不断接收数据以更新某些仪表值。

我遇到的问题是,当读取串口时,如果数据过快,我的应用程序响应速度非常慢,例如读取时数据速率为1000Hz。

我附上了我的代码的简化版本。

什么可能导致此应用程序挂起?我读到我需要一些单独的线程?但是如何实现这个目标呢?

namespace Motor
{
    public partial class Form1 : Form
    {
        SerialPort ComPort = new SerialPort();
        string InputData = String.Empty;
        delegate void SetTextCallback(string text);

        public Form1()
        {
            InitializeComponent();
            ComPort.DataReceived += 
                new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived_1);
        }

        private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
        {
            InputData = ComPort.ReadExisting();
            if (InputData != String.Empty)
            {
                this.BeginInvoke(new SetTextCallback(SetText), new object[] { InputData });
            }
        }

        private void SetText(string text)
        {
            if (text.Contains("CM")) 
            {
                // process the text content here
            }
        }
    }
}

4 个答案:

答案 0 :(得分:2)

这很可能是你的问题

this.BeginInvoke(new SetTextCallback(SetText), new object[] { InputData });

如果您的串口正在颠簸,它会一直尝试编组回UI线程。你真的需要这么快更新主UI线程吗?你不能每一秒或定期做这件事

关于声明

  

什么可能导致此应用程序挂起?我读到我需要一些   单独的线程?但是如何实现这个目标呢?

SerialPort.DataReceived Event

  

当数据出现时,在辅助线程上引发DataReceived事件   从SerialPort对象

收到

即它已经在辅助线程上运行,因此启动另一个线程无法帮助您

<强>更新

参考您的评论

  

1000hz是来自硬件的数据速率,它不需要   GUI要那么快,但我希望仪表能够顺利移动。

你仍然可以使它们流畅,至少仍然阻止UI限制将是你的关键,尝试缓冲200-300毫秒左右。我只是玩弄它

答案 1 :(得分:0)

使用function deleteObj(x){ var params = {Bucket: bucketName, Key: x.fileName}; bucket.deleteObject(params, function(err, data) { if (err) console.log(err, err.stack); // an error occurred }); } 来避免分块ReadLine

Data Recieved

本部分namespace Motor { delegate void SetTextCallback(string text); public partial class Form1 : Form { SerialPort ComPort = new SerialPort(); string InputData = String.Empty; SetTextCallback st; public Form1() { InitializeComponent(); st = new SetTextCallback(SetText); } private void Form1_Load(object sender, EventArgs e) { OpenPort(); } private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e) { InputData = ComPort.ReadLine(); if (InputData != String.Empty) { this.Invoke(st,new object[] { InputData}); } } private void SetText(string text) { Console.WriteLine(text);//To check the return value if (text.Contains("CM")) { // process the text content here } } } } ;

中有很多回报值

返回值列表(小心检查此值)

InputData

还有其他人......

现在,当你想要放弃或继续使用该值返回的代码时,它取决于你的代码。

在此代码之前,您已打开1. OK 2. > 3. + CMGS: ID_NUMBER_HERE 4. ERROR ERROR_NUMBER_HERE 。如果PORT已关闭,则此代码不再有效。

打开港口指南

PORT

希望它有所帮助。

答案 2 :(得分:-1)

我没有编写任何示例代码,但我可以建议您使用线程后台工作者来读取数据,这很容易理解背景工人或线程。你可以看简短的教程。尝试创建一个启动后台工作人员的按钮,然后使用该后台工作人员,您可以读取数据而不冻结。抱歉,我没有时间写例子,但在我看来,这些是主题你应该专注 (Bakcground worker or Threads) < / p>

我希望这会有所帮助。

答案 3 :(得分:-2)

尝试实现async await

更多信息: https://docs.microsoft.com/en-us/dotnet/csharp/async

https://msdn.microsoft.com/en-us/library/hh156513(v=vs.120).aspx

这是一个简单的例子(虽然我无法验证它,因为我没有运行代码的必要条件,但应该提出一个想法):

namespace Motor
{
public partial class Form1 : Form
{
    SerialPort ComPort = new SerialPort();
    string InputData = String.Empty;
    delegate void SetTextCallback(string text);

    public Form1()
    {
        InitializeComponent();
        ComPort.DataReceived +=
            new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived_1);
    }

    private async void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
    {
        var size = ComPort.ReadBufferSize;
        var data = new byte[size];
        await ComPort.BaseStream.ReadAsync(data,0,size);
        InputData += ComPort.Encoding.GetString(data);
        SetText(InputData);
    }


    private void SetText(string text)
    {
        if (text.Contains("CM"))
        {
            // process the text content here

        }
    }


}
}