【问题标题】:Problems with SerialPort class in .NET.NET 中的 SerialPort 类问题
【发布时间】:2012-03-21 20:00:41
【问题描述】:

我正在尝试诊断为什么某些 USB 串行端口适配器不能很好地与 .NET 配合使用。受影响适配器的行为在SerialPort.Write() 之后。调用任何 SerialPort.Readxxx() 方法导致该方法阻塞直到大约 ReadTimout。 我发现的解决方法是使用循环阻止 BytesToRead<= 0,然后一切都按预期工作。为什么?

我使用Sysinternals'Portmon 收集了some debug logs。为什么会这样?

without.log = bad behavior/bad USB adapter
with.log = with the while loop/bad USB adapter
ftdi.log = good behavior/good USB adapter

我编写了 ReadByte() 的两个本机实现,现在可以更好地描述问题。 将 ReadIntervalTimeout 和 ReadTotalTimeoutMultiplier 设置为 MAXDWORD ReadFile(),它是 应该等到一个字节在接收缓冲区中并按照 MSDN 中的描述返回 COMMTIMEOUTS 结构页面。

Portmon 日志显示这是 ReadByte() 设置串行端口的方式。但如果 当调用 ReadFile() 时接收缓冲区为空 ReadFile() 它等到 ReadTotalTimeoutConstant 然后返回。 微软的 ReadByte() 也设置了一个 Comm 事件; Portmon 日志清楚地显示事件正在触发,但 ReadByte() 从不读取接收缓冲区。我在本机版本的 ReadByte() 中实现了这一点,它与受影响的 USB 转串口适配器完美配合。

Native ReadByte()

【问题讨论】:

    标签: c# .net debugging usb serial-port


    【解决方案1】:

    读取 SerialPort 的最佳方法是使用异步方法:

    _port = new SerialPort();
    _port.DataReceived += new SerialDataReceivedEventHandler(OnComPortDataReceived);
    
    void OnComPortDataReceived(object sender, SerialDataReceivedEventArgs e)
    {
       byte[] ba = new byte[_port.BytesToRead];
       total = _port.Read(ba, 0, _port.BytesToRead);
    }
    

    【讨论】:

    • DataReceivedEvent 不能保证触发,在我的测试中,40% 的事件永远不会到达应用程序
    • 您能解释一下为什么“DataReceivedEvent 不能保证触发”吗?
    • 相当奇怪的问题。也许您的适配器工作不正常。我检查了我的旧 GSM 手机(作为调制解调器连接到 USB),尝试发送一些 AT 命令,一切正常。我也用portmon检查过...你能把你的代码贴在这里吗?
    • 我想,你是 C/C++ 程序员 :) 当我来到 C# 时,我以同样的方式使用串行。但是你应该切换到事件,真的!我建议您在 DataReceivedEvent 处理程序中记录每个字节并检查是否所有数据都来了
    • 这段代码是用来移动望远镜的,我有两个不受控制的回转试图使用事件,对于我的使用来说不够可靠。我有一个 DataRecievedEvent 处理程序,它所做的只是增加一个计数器,发现多达 40% 的事件丢失了。天气与否我应该使用事件不是问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 2013-11-14
    • 2011-10-30
    • 2011-10-04
    • 1970-01-01
    相关资源
    最近更新 更多