C#串口在收到数据后挂起

时间:2016-09-22 03:59:29

标签: c#

这是我的代码

    public void ClosePort()
    {
        if (comPort.IsOpen == true)
        {
            Thread CloseDown = new Thread(() => CloseSerialOnExit(comPort)); //close port in new thread to avoid hang

            CloseDown.Start(); //close port in new thread to avoid hang
        }
    }

    private void CloseSerialOnExit(SerialPort port)
    {
        port.DiscardOutBuffer();
        port.Close();

        DisplayData(MessageType.Error, "Port communication has been closed" + " " + DateTime.Now + "\n");
    }

为什么当我的应用程序收到数据关闭不起作用?这种情况的另一种解决方案是什么?我的工作步骤是:

  1. 连接端口,
  2. 扫描并接收数据,
  3. 断开端口,并再次从连接端口重复启动,但是当我们要启动连接端口时,系统显示错误消息:
  4.   

    访问com端口被拒绝。

    我发生的事情是因为端口实际上并不接近。如何关闭端口?

    这是我在开放端口的代码

    public bool OpenPort()
        {
            try
            {
                //first check if the port is already open
                //if its open then close it
                if (comPort.IsOpen == true) comPort.Close();
    
                //set the properties of our SerialPort Object
                comPort.BaudRate = int.Parse(_baudRate);    //BaudRate
                comPort.DataBits = int.Parse(_dataBits);    //DataBits
                comPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), _stopBits);    //StopBits
                comPort.Parity = (Parity)Enum.Parse(typeof(Parity), _parity);    //Parity
                comPort.Handshake = (Handshake)Enum.Parse(typeof(Handshake), _parity);    //Parity                
                comPort.PortName = _portName;   //PortName
                //now open the port
                comPort.WriteTimeout = 400;//Write timeout, if the efficiency of the serial driver software, can effectively avoid the deadlock
                comPort.ReadTimeout = 400;//Read timeout, ibid
                comPort.Open();
                comPort.DtrEnable = false;
                comPort.RtsEnable = false;
                //display message
                DisplayData(MessageType.Normal, "Port opened at " + DateTime.Now + "\n");
                //return true
                return true;
            }
            catch (Exception ex)
            {
                DisplayData(MessageType.Error, ex.Message);
                return false;
            }
        }
    

    这是我在comPort_datareceived中的代码

    void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
                //determine the mode the user selected (binary/string)
                switch (CurrentTransmissionType)
                {
                    //user chose string
                    case TransmissionType.Text:
                        //read data waiting in the buffer
                        string msg = comPort.ReadExisting();
                        //display the data to the user
                        DisplayData(MessageType.Incoming, msg + "\n");
                        break;
                    //user chose binary
                    case TransmissionType.Hex:
                        //retrieve number of bytes in the buffer
                        int OpeCode = 0;
                        int RequestID = 0;
                        int Product = 0;
                        int IPenNo = 0;
                        string status = " ";
    
                        while (true)
                        {
                            DateTime time = DateTime.Now;             // Use current time.
                            string format = "dddddddd, MMMMM d, yyyy HH:mm:ss";
                            string currentTime = time.ToString(format);
                            byte[] TrueData = new byte[256];
    
                            try
                            {
                                int bytes = comPort.BytesToRead;
                                if (bytes == 0) continue;
                                //create a byte array to hold the awaiting data
                                byte[] comBuffer = new byte[bytes];
                                comPort.Read(comBuffer, 0, bytes);
                                DisplayData(MessageType.Incoming, "Hexa :" + ByteToHex(comBuffer) + "\n");
                                DisplayData(MessageType.Incoming, "Byte :" + bytes.ToString() + "\n");
    
                                if (bytes == 3)
                                {
                                    var lines = File.ReadAllLines(Fullpath).ToList();
    
                                    // Remove as many lines as you'd like from the end
                                    if (lines.Count > 2)
                                    {
                                        lines.RemoveRange(lines.Count - 2, 2);
                                    }
    
                                    // Iterate backwards through the list until we've updated 2 (or more or less) lines
                                    var linesUpdated = 0;
    
                                    for (var i = lines.Count - 1; i >= 0 && linesUpdated < 1; i--)
                                    {
                                        if (lines[i].Contains("OK"))
                                        {
                                            lines[i] = lines[i].Replace("OK", "NG");
                                            linesUpdated++;
                                        }
                                    }
    
                                    File.WriteAllLines(Fullpath, lines.ToArray());
                                    //DisplayData(MessageType.Incoming, "NG" + "\n");
                                }
    
                                if (bytes == 2)
                                {
                                    continue;
                                }
    
                                int etx_ok = 0;
    
                                for (int i = 0; i < bytes; i++)
                                {
                                    if (comBuffer[i] == 0x02)
                                    {
                                        //DisplayData(MessageType.Incoming, "cek II:" + checkStatus + "\n");
                                        int length = comBuffer[i + 1];
                                        DisplayData(MessageType.Incoming, "Length=" + length.ToString() + "\n");
    
                                        if (String.IsNullOrEmpty(bytes.ToString()))
                                        {
                                            status = "NG";
                                        }
                                        if (length + i + 1 != bytes && status == " ")
                                        {
                                            DisplayData(MessageType.Incoming, length.ToString() + " " + i.ToString() + " " + bytes.ToString() + " ");
                                            status = "NG";
                                            DisplayData(MessageType.Incoming, "ERROR \n");
                                            //break;
                                        }
                                        else
                                        {
                                            status = "OK";
                                        }
    
                                        DisplayData(MessageType.Incoming, "ini statusnya  : " + status + "\n");
    
                                        if (comBuffer[length + i - 1] == 0x03)
                                        {
                                            DisplayData(MessageType.Incoming, "ETX OK\n");
                                            etx_ok = 1;
                                            OpeCode = comBuffer[i + 2];
                                            DisplayData(MessageType.Incoming, "OpeCode=" + OpeCode.ToString() + ",");
                                            RequestID = comBuffer[i + 3];
                                            DisplayData(MessageType.Incoming, "RequestID=" + RequestID.ToString() + ",");
                                            int StoreCode = comBuffer[i + 4];
                                            DisplayData(MessageType.Incoming, "StoreCode=" + StoreCode.ToString() + ",");
                                            int ProductBatteryTraining = comBuffer[i + 5];
                                            DisplayData(MessageType.Incoming, "ProductBatteryTraining=" + ProductBatteryTraining.ToString() + ",");
    
                                            Product = ProductBatteryTraining >> 4;
                                            DisplayData(MessageType.Incoming, "  Product=" + Product.ToString() + ",");
                                            int Battery = ProductBatteryTraining & 4;
                                            DisplayData(MessageType.Incoming, "  Batery=" + Battery.ToString() + ",");
                                            int Training = ProductBatteryTraining & 1;
                                            DisplayData(MessageType.Incoming, "  Training=" + Training.ToString() + ",");
    
                                            IPenNo = comBuffer[i + 6];
                                            DisplayData(MessageType.Incoming, "IPenNo=" + IPenNo.ToString() + ",");
    
                                            int CrcCalc = comBuffer[length + i] + 0x11;
    
                                            for (int j = 7, k = 0; j < length; j++, k++)
                                            {
                                                //syswrite STDOUT , "TrueDataX " . $length . "\n";
                                                DisplayData(MessageType.Incoming, "TrueDataX " + length.ToString() + "," + "\n");
                                                TrueData[k] = comBuffer[i + j];
                                            }
                                            if (OpeCode == 0x63)
                                            {
                                                byte[] replyStr = new byte[] { 
                                            Convert.ToByte(0x45), Convert.ToByte(0x53), Convert.ToByte(0x4c), Convert.ToByte(0x14), Convert.ToByte(0x09), Convert.ToByte(0x00),                             //#Length Change
                                            Convert.ToByte(0x02), Convert.ToByte(0x08),Convert.ToByte(OpeCode), Convert.ToByte(RequestID),Convert.ToByte(Product-1), Convert.ToByte(IPenNo),                                       //#Reply Header Data                   
                                            Convert.ToByte(0x00),                                                                                                                                           //#Reply Status      
                                            Convert.ToByte(0x03), Convert.ToByte(CrcCalc),                                                                                                                     //#Footer Data    
                                            Convert.ToByte(0xcc), Convert.ToByte(0xcc) 
                                            };
    
                                                comPort.Write(replyStr, 0, replyStr.Length);
    
                                                //write file to textfile
                                                //string path = @"d:\yosafat\testfile\tes1_Friday0916201614.33.txt"; 
                                                string IPenID = IPenNo.ToString();
                                                string appendText = ("IPen ID \t" + "Datetime\t\t\t\t\t" + "Status" + Environment.NewLine + IPenID + "\t\t" + currentTime + "\t\t" + status + Environment.NewLine);
                                                File.AppendAllText(Fullpath, appendText);
                                            }
                                        }
                                        else
                                        {
                                            OpeCode = 0;
                                            //syswrite STDOUT , "ETX Bad Data" . $length . "\n";
                                            DisplayData(MessageType.Incoming, "ETX Bad Data" + length.ToString() + "\n");
                                            break;
                                        }
                                    }
                                    if (etx_ok == 1)
                                    {
                                        break;
                                    }
                                }
                            }
                            catch (Exception) { }
                        }
                }
            }
        public static int GetFirstOccurance(byte byteToFind, byte[] byteArray)
        {
            return Array.IndexOf(byteArray, byteToFind);
        }
    

2 个答案:

答案 0 :(得分:1)

为什么要在单独的帖子中调用CloseSerialOnExit?同步调用它不是更容易吗?真的花了很多时间吗?

无论如何,如果你需要它,你应该确保在线程完成之前Thread对象不是GC。你应该让CloseDown成为会员。

您还可以使用某些同步来查看ClosePort是否已在OpenPort的开头处完成。

Thread CloseDown = null;
public void ClosePort()
{
    if (comPort.IsOpen == true)
    {
        CloseDown = new Thread(() => CloseSerialOnExit(comPort)); //close port in new thread to avoid hang
        CloseDown.Start(); //close port in new thread to avoid hang
    }
}

答案 1 :(得分:1)

return事件处理程序的catch块内添加SerialPort.DataReceived,以便在发生while的情况下退出exception循环。

while (true)
{
    //...
    try {
        //...
    } catch (Exception) { return; //add this}
}

在另一个线程Close之后,在读取数据时可能会出现Exception(此行:comPort.Read(comBuffer, 0, bytes);)。如果没有return语句,您将永远不会退出while循环,GC也不会处理 SerialPort 。因此,当您尝试重新打开端口时,您将失败。