3

我在 C# 中遇到了虚拟串行端口的问题:当我调用 Write 函数时,它会自动抛出 TimeOutException,但客户端会收到数据。

它只发生在虚拟端口上(我正在使用 HDDSoftware 的免费虚拟串行端口,带有桥 COM12<->COM13)。我用 Visual Studio 打开 COM12,用 Hercules 打开 COM13。应用程序抛出超时异常,但 Hercules 收到消息。

我设置 1000 毫秒或 1000000 毫秒的读/写端口超时都没关系。

谢谢!!

        using (SerialPort port = new SerialPort("COM13"))
        {
            // configure serial port
            port.BaudRate = 9600;
            port.DataBits = 8;
            port.Parity = Parity.None;
            port.StopBits = StopBits.One;
            port.Open();

            port.ReadTimeout = 10000;

            byte[] buffer = Encoding.ASCII.GetBytes("HELLO WORLD");

            try
            {
                port.Write(buffer, 0, buffer.Length);
            }
            catch(TimeoutException)
            {
                Console.WriteLine("Write timeout");
            }

            Console.WriteLine(DateTime.Now.ToString("HH:mm:ss"));
            try
            {
                byte[] buf = new byte[100];
                port.Read(buf, 0, 1);
            }
            catch(IOException)
            {
                Console.WriteLine("Read timeout");
            }
            Console.WriteLine(DateTime.Now.ToString("HH:mm:ss"));
        }

经过几次测试(将 Write 放入 try-catch 中),Read 操作也会立即抛出 TimeOutException。

这是我在运行测试时得到的。它应该是:12:16:06(读取超时)12:16:16

在此处输入图像描述

4

2 回答 2

2
   port.Write(buffer, offset, count);

由设备驱动程序决定如何实现它。但我所知道的所有这些都遵循允许底层WriteFile()调用返回 *lpNumberOfBytesWritten < nNumberOfBytesToWrite 的规则。或者换句话说,写入不是“事务性的”。

一个体面的心智模型是 Write()一次从缓冲区写入一个字节,计数次。在某些时候,完全不可预测的是,当驱动程序的传输缓冲区已满且无法存储另一个字节时,再写入一个字节将停止。最终触发异常。

所以缓冲区的一部分仍然会到达另一端。您无法分辨 SerialPort 类的哪个部分。超时是一种严重的通信故障,很难从中恢复。如果这是一个显示停止器,那么您需要考虑一次写入一个字节(很好,串行端口很慢)或注意 WriteBufferSize - BytesToWrite 以检查缓冲区是否适合并实现您自己的超时。

于 2014-08-22T15:20:18.557 回答
0

正如 Hans Passant 所说,这是 Virtual COM 软件的问题。我尝试使用 Eltima Software 的虚拟串行端口并且工作正常!

于 2014-08-22T19:36:38.273 回答