C#winform冻结:串行端口,计时器,线程

时间:2020-07-27 22:29:49

标签: c# winforms timer

编辑:保留原始问题的连续性。 然后,我通过使用ReadExisting来使用带有替换代码的ReadLine()方法来编辑问题。它可以工作,但是我仍然遇到同样的问题,该应用程序变得无响应。 Debug表示它在while(){}函数中处于锁定状态(冻结需要一些时间,有时是几秒钟,有时是几分钟),在该函数中,我等待完整的消息。以下是更多说明:

-已过时-

什么是处理serialport.readtimeout异常的好方法?

                    try
                    {
                        serialPort1.Write(Command_);
                        if (!IsWriteComm_)
                        {
                            Response_ = serialPort1.ReadLine().Replace("\r", "");
                        }
                    }
                    catch (TimeoutException err)
                    {
                        DateTime d = DateTime.Now;
                        rtboxDiag.AppendText("\n" + d.ToString("HH:mm:ss") + ": ");
                        rtboxDiag.AppendText(err.Message);
                        if (!serialPort1.IsOpen)
                            InitConnection();
                        return Textbox_;
                    }

这部分代码在计时器滴答事件中被执行。 我的应用发生异常的“崩溃”,但出现IO异常

“由于线程退出或应用程序请求,I / O操作已中止。”

无论我做什么,我都无法“恢复”含义,我不再能够从串行端口轮询数据。

我添加了此异常捕获,它确实记录了异常。奇怪的是,对!serialport.isopen的测试是错误的(意味着端口仍处于打开状态)。

可能是一个提示:该错误确实使计时器停止运行,这不是我在代码中所做的事情。所以我怀疑与计时器有关的东西,而不是与串行端口有关的东西,但是我可能是错的。

手动关闭端口,然后重新连接不能解决问题。 断开并重新连接USB不能解决问题。

但是,关闭应用程序,然后重新启动应用程序确实可以解决问题(甚至无需断开MCU或重新启动MCU /硬件)。

-/过时-

编辑:问题是在几秒钟后出现的,有时需要几分钟才能完成。我无法使用串行端口终端以相同的方式,以相同的频率轮询数据来重复该问题。看来问题不在于硬件本身。

欢呼

编辑:我尚未测试以下修改,不确定是否能解决此问题(我怀疑),但至少是尝试不使用.readline(),但从我收集到的结果来看这不好练习。

反正这里是

                    try
                    {
                        serialPort1.Write(Command_);
                        if (!IsWriteComm_)
                        {
                            while (!SerialRxCplt) ;
                            Response_ = SerialRxResponse.Replace("\r", "").Replace("\n", "");
                            SerialRxCplt = false;
                            //Response_ = serialPort1.ReadLine().Replace("\r", "");
                        }
                    }
                    catch (TimeoutException err)
                    {
                        DateTime d = DateTime.Now;
                        rtboxDiag.AppendText("\n" + d.ToString("HH:mm:ss") + ": ");
                        rtboxDiag.AppendText(err.Message);
                        if (!serialPort1.IsOpen)
                            InitConnection();
                        return Textbox_;
                    }

并且我启用了datareceived事件:

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            var serialPort = (System.IO.Ports.SerialPort)sender;
            string dataReceived = serialPort.ReadExisting();
            ProcessSerialData(dataReceived);
        }

这就是我处理数据的方式,并手动“等待” \ n字符,该字符告诉我何时完全接收到数据。

private void ProcessSerialData(string data)
        {
            SerialRxBuffer += data;
            if (SerialRxBuffer.Contains("\n"))
            {
                SerialRxCplt = true;
                SerialRxResponse = SerialRxBuffer;
                SerialRxBuffer = "";
            }
            else
            {
                SerialRxCplt = false;
            }
        }

欢迎任何输入。

我在while循环中添加了用于调试的“东西”,它在一段时间内运行良好,然后冻结,没有错误或异常抛出。由于某种原因,我感觉它与串行端口无关。 我什至添加了这个:

                    try
                    {
                        serialPort1.Write(Command_);
                        if (!IsWriteComm_)
                        {
                            Stopwatch stopWatch = new Stopwatch();
                            stopWatch.Start();
                            while (!SerialRxCplt || Timer2StopWatchMilli > 5)
                            {
                                Timer2StopWatchMilli = stopWatch.Elapsed.TotalMilliseconds;
                                ExceptionMessage = Timer2StopWatchMilli.ToString();
                                IsException = true;
                            }
                            stopWatch.Stop();
                            if (!SerialRxCplt)
                                return Textbox_;
                            Response_ = SerialRxResponse.Replace("\r", "").Replace("\n", "");
                            SerialRxCplt = false;
                            //Response_ = serialPort1.ReadLine().Replace("\r", "");
                        }
                    }

ExceptionMessage和IsException帮助我了解该循环中发生的事情。在正常操作中,您将只需要按0.0x毫秒的增量递增。数据正在正确处理。当它冻结时,看起来没有异常。最初,我以某种方式陷入无限循环,但是|| Timer2StopWatchMilli> 5应该让我摆脱困境,这有点超时。

另外一条信息:冻结时,一个CPU内核已满载。 (我有一个6核CPU,在任务管理器中占16-17%-内存使用率不足<30MB)

欢迎任何帮助

1 个答案:

答案 0 :(得分:0)

我通过在每次成功交易后清除RX / TX和流缓冲区来修复它。 我认为将数据发送到PC的速度比读取数据的速度快,导致数据最终在Rx缓冲区上累积。

private void SerialPortClearBuffers()
        {
            serialPort1.DiscardOutBuffer();
            serialPort1.DiscardInBuffer();
            serialPort1.BaseStream.Flush();
        }
相关问题