我试图以非常快的速度连续从串口获取数据。波特率为230400
。
当我打印出数据,时间戳以及BytesToRead
到文件时,我注意到只要BytesToRead
下降到一个数字且readLine()
没有读取任何内容,就会发生200毫秒的延迟200毫秒。延迟之后,BytesToRead
会回到3000左右,这个过程会一次又一次地发生。基本上我不是在不断获取数据。
我想也许我读的速度比缓冲区中的速度数据更快,所以我尝试更改readBuffer大小并让这个线程休眠1ms,以便让缓冲区保持我正在读取的速度。他们都没有工作。还有一些延迟。
欢迎任何想法。
private void dostuff()//The thread I created after the port is opened
{
var startTime = DateTime.Now;
var stopwatch = Stopwatch.StartNew();
while (serialPortEncoder.IsOpen)
{
if (serialPortEncoder.BytesToRead > 210)
{
try
{
var line = serialPortEncoder.ReadLine();
var timestamp = (startTime + stopwatch.Elapsed);
var lineString = string.Format("{0} ----{1}",
line,
timestamp.ToString("HH:mm:ss:fff") + " "+serialPortEncoder.BytesToRead+"\r\n");
richTextBoxEncoderData.BeginInvoke(new MethodInvoker(delegate()
{
richTextBoxEncoderData.Text = line;//update UI
}));
}
catch (Exception ex) { MessageBox.Show(ex.ToString()); }
}}
答案 0 :(得分:2)
除非每210个字节有一个换行符,否则ReadLine()函数可能会超时并且不返回任何内容。 ReadLine()将读取输入缓冲区,直到遇到换行值,然后返回它之前的任何数据。 http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.readline.aspx
港口有什么样的信息?如果要读取特定大小的缓冲区,只需使用Read
方法。如果你需要阅读直到换行,请使用ReadLine()并经常检查它是否返回一个字符串。
答案 1 :(得分:2)
您的代码存在根本性缺陷,它受到“热等待循环”错误的影响。当串行端口没有足够的数据时,您的循环正在燃烧100%核心。这将使Windows在你烧掉量子之后将你的线程放入狗屋一段时间,让其他线程有机会运行。在那个狗屋里待200毫秒有点长,但肯定并不罕见。
你应该采取不同的方式,当有可用的串口数据时,你应该让Windows有机会叫醒你。当它查找要调度的下一个线程时,它支持具有I / O完成的线程。这很容易做到,只需删除BytesToRead测试即可。 ReadLine()调用是一个阻塞调用,在收到NewLine之前不会返回。你的线程现在将消耗接近0%的cpu周期。
当机器负载过重或垃圾收集器运行时,您仍将丢失任意时间。不,这不足以可靠地读取编码器并关闭反馈回路。可靠地执行此操作需要具有可预测的实时行为的微控制器。随时可从工业电子供应商处获得。
答案 2 :(得分:0)
在对网络进行了一些无休止的研究之后,我找到了延迟的原因。设备管理器--->端口---->提前---->将延迟改为1ms将解决问题。现在,每当缓冲区降至零时,最多只需2ms即可恢复正常。我现在使用单独的线程轮询数据。它运作得很好。
但就像Hans Passant所说的那样,我正试图想出一个更好的设计方法。