c# - System.IO.Ports.dll 错误中的 System.TimeoutException

标签 c# console serial-port

我编写了一个设置参数的控制台c#程序(我从项目->调试选项中给出了参数)我试图从以太网和串行端口获取数据。

我成功设置了 args 参数,但程序在 string filename = args[4]; 控制台突然打开处出现超时错误,并且表现得好像它处于无限循环中,但是没有循环。(在读取 while 之前发生错误)

对于那些想了解这些参数是什么的人; 1 = IP,[2] = 端口号,[3] = 端口名称(COM3),[4] = 文件名。

[编辑] 考虑到我可能同时从以太网和串行端口的两个连接获取数据,超时是为了防止数据丢失。

此外,我想说添加 DataReceived += new SerialDataReceivedEventHandler(ProcessReceivedData); 而不是 while 没有任何好处,因为它再次发生在 while 循环之前。

有人知道吗?

error and parameters I gave

static int Main(string[] args)
        {

            int err = 0;

            if (args.Length == 5)
            {
                IPAddress IP = IPAddress.Parse(args[1]);
                int CmdPort;
                if (int.TryParse(args[2],out CmdPort))
                {
                    string filename = args[4];//takes filename 

                    String root = @".\\"; //DEFAULT EXE PATH ROOT
                    string path_combined;
                    path_combined = Path.Combine(root, filename);
                    StreamWriter sw;
                    try
                    {
                        sw = File.AppendText(path_combined);
                        p = new SPWrapper(IP, CmdPort, args[3], sw);
                        if (p.Init())
                        {
                            while (!Console.KeyAvailable)
                            {
                                p.GetMessage();
                                Thread.Sleep(100);
                            }
                            p.Close();
                        }
                        sw.Flush();
                        sw.Close();
                    }
                    catch (System.IndexOutOfRangeException ex)
                    {
                        System.ArgumentException argEx = new System.ArgumentException("File creation failed!", ex);
                        err = -2;
                        throw argEx;
                    }
                }
                else
                {
                    err = -1;
                }
            }
            if (err!=0)
            {
                Console.WriteLine("Not Enough Arguments");
                Console.WriteLine("Logger IP Port ComPort FileName");
            }
            return err;
        }//end of main

Here is my other class

 public class SPWrapper
{
    private System.IO.Ports.SerialPort CmdSerialPort;

    public DateTime lastComm = DateTime.MinValue;
    public UdpClient udpClient_Cmd;
    public volatile bool _enabled_Cmd;
    public static int Ethernet_Packet_Header_Length = 14;
    private IPAddress IP { get; set; }
    private int Cmd_Port { get; set; }
    private string SerialPortName;
    private StreamWriter swLog;
    private bool _closing = false;
    private IPEndPoint IPE_Cmd;


    private void CloseEthernet()
    {
        udpClient_Cmd?.Close();
    }

    private void CloseSerialPort()
    {
        if (CmdSerialPort.IsOpen)
        {
            CmdSerialPort.Close();
        }
    }

    public void Close()
    {
        _closing = true;
        CloseEthernet();
        CloseSerialPort();
        swLog = null;
    }

    private bool InitilizeSerialPort(string portName)
    {
        try
        {
            CmdSerialPort.PortName = portName;
            CmdSerialPort.BaudRate = 115200;
            CmdSerialPort.ReadTimeout = 10; // 10milisecond read timeout

            CmdSerialPort.Open();
            if (CmdSerialPort.IsOpen)
            {
                return true;
            }
            return false;
        }
        catch (UnauthorizedAccessException e)
        {
            Debug.WriteLine(e.ToString());
            Debug.WriteLine(e.Message);
            return false;
        }
        catch (ArgumentOutOfRangeException e)
        {
            Debug.WriteLine(e.ToString());
            Debug.WriteLine(e.Message);
            return false;
        }
        catch (ArgumentException e)
        {
            Debug.WriteLine(e.ToString());
            Debug.WriteLine(e.Message);
            return false;
        }
    }

    private bool InitializeEthernet()
    {
        bool retVal = true;
        IPE_Cmd = new IPEndPoint(IP, Cmd_Port);
        try
        {
            udpClient_Cmd = new UdpClient();
            udpClient_Cmd.Client.Bind(IPE_Cmd);
            udpClient_Cmd.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 10);
        }
        catch (Exception ex)
        {
            retVal = false;
            udpClient_Cmd?.Close();
            udpClient_Cmd = null;
            Debug.WriteLine(ex.ToString());
            Debug.WriteLine(ex.Message);
            Debug.WriteLine(ex.InnerException?.ToString());
        }
        return retVal;
    }

    public SPWrapper(IPAddress ip, int cmdPort, string comPort, StreamWriter sw)
    {
        IP = ip;
        Cmd_Port = cmdPort;
        SerialPortName = comPort;
        swLog = sw;
        CmdSerialPort = new SerialPort();
    }

    public bool Init()
    {
        return (InitializeEthernet() && InitilizeSerialPort(SerialPortName));
    }

    internal void GetMessage()
    {
        lastComm = DateTime.Now;
        string SerialMessage = "";
        try
        {
            SerialMessage = CmdSerialPort.ReadLine();
        }
        catch (TimeoutException)
        {
        }
        if (SerialMessage.Length >0)
        {
            SerialMessage = SerialMessage.Trim(' ').Trim('\n').Trim('\r');
            swLog.WriteLine($"{CmdSerialPort.PortName}\t{lastComm}\t{SerialMessage}");
        }
        IPEndPoint e = new IPEndPoint(IPAddress.Any, 0);
        byte[] receiveBytes = null;
        try
        {
            receiveBytes = udpClient_Cmd?.Receive(ref e);
        }
        catch (ObjectDisposedException)
        {
            udpClient_Cmd?.Close();
            udpClient_Cmd = null;
        }
        catch(SocketException)
        {
        }
        if (receiveBytes != null)
        {
            string UDP_Read_Message = System.Text.Encoding.UTF8.GetString(receiveBytes.Skip(Ethernet_Packet_Header_Length).ToArray());
            swLog.WriteLine($"{e}\t{lastComm}\t{UDP_Read_Message}");
        }
    }
}

最佳答案

经过评论里和你的讨论,我想我可以回答你的问题了。

该错误绝对与您怀疑的那行没有任何关系,因为您已经发现了这一点。

您收到一个 TimeoutException ,这是有道理的,因为在 InitilizeSerialPort 中您将读取超时设置为 10ms。这非常短,特别是考虑到您正在阅读整行,而不仅仅是几个字节。
你确实在那里使用了更大的数字。默认值为 500 毫秒,这是一个相当不错的时间。如果您确实需要降低,请尝试一下,但在大多数情况下您不需要更改它。由于您正在阅读一整行,因此实际上 500 毫秒很可能还不够,具体取决于您每行获得的信息量。尝试一些值,直到它起作用(但如果 90 就足够了,请不要将其设置为 100,而是给它一点空间)。

也许值得一提的是,超时当然是最大值。如果指定 1000ms,并且读取需要 100ms,它将在 100ms 后返回,而不等待超时。 要解决此问题,您可以完全删除设置 ReadTimeout 属性的行(它将使用默认值 500 毫秒)或自行将其设置为更高的值。

遗憾的是,我无法帮助您解决您在上一条评论中提到的UnauthorizedAccessException,因为这很大程度上取决于您的设置。如果您需要帮助,您应该提出一个新问题。

编辑:
顺便说一句,您完全在 GetMessage 中吞下了 TimeoutException 。不要那样做。当另一个错误发生时,您已经在编写控制台消息,因此也可以在那里执行此操作。 SocketException 也是如此,它只是被同一个方法吞掉了。 永远不要吞下异常

关于c# - System.IO.Ports.dll 错误中的 System.TimeoutException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57675933/

相关文章:

c# - 如何获取 GridViewColumnHeader Click 事件上的 ListViewControl

python - 在模式 6 python gekko 下运行时没有求解器显示

linux - 让两个 Linux(虚拟)盒子通过串口通话

java - 为 System.in 设置环境

.net - 在 WPF 窗口中嵌入控制台窗口

php - 通过php访问串口

serial-port - 如何通过串口传输二进制文件?

java - 将一些获取和设置代码从 C# 转换为 Java

c# - System.Drawing.dll 附加信息 : Out of memory 中发生类型为 'System.OutOfMemoryException' 的未处理异常

c# - X509CertificateCollection 中的 Mono NotImplementedException