簡體   English   中英

C# winforms 凍結:串口、定時器、線程

[英]C# winforms freezing: Serialport, Timer, Thread

編輯:保持原始問題的連續性。 然后,我改用 ReadExisting 用 ReadLine() 方法的替換代碼編輯了問題。 它可以工作,但是我仍然有同樣的凍結,應用程序變得無響應。 Debug 說它在 while () {} function 中鎖定(凍結需要一段時間,有時是幾秒鍾,有時是幾分鍾),我在那里等待完整的消息。 更多解釋如下:

- 過時的 -

處理 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 操作已中止。”

無論我做什么,我都無法“恢復”意思,我不再能夠從串口輪詢數據。

我添加了這個異常捕獲,它確實記錄了異常。 奇怪的是,測試 on.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% - memory 使用率低 < 30MB)

歡迎任何幫助

我通過在每次成功交易后清除 RX/TX 和 stream 緩沖區來修復它。 我認為數據發送到 PC 的速度比它能夠讀取的速度更快,導致數據最終累積在 Rx 緩沖區中。

private void SerialPortClearBuffers()
        {
            serialPort1.DiscardOutBuffer();
            serialPort1.DiscardInBuffer();
            serialPort1.BaseStream.Flush();
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM