2016-09-22 82 views
0

這是我的代碼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. 斷開連接端口,並重復連接端口重新開始,但是當我們要開始連接端口,系統顯示錯誤信息:

接入端口被拒絕。

我發生這種情況,因爲港口實際上並沒有關閉。如何關閉端口?

這是我在打開端口的代碼

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); 
    } 
+0

'Close'和'Open'之間的時間間隔有多長?爲什麼你需要重複打開/關閉?我最好讓端口保持打開狀態。 – putu

+0

@IPutuSusila是的,我必須關閉端口,因爲接收到的數據將保存到文本文件,當點擊按鈕斷開將結束掃描和接收數據。 – yosafat

+0

當然,您需要關閉時,即通過斷開按鈕。那麼,你的意思是,在你點擊斷開連接按鈕後,當你點擊連接時,錯誤會上升?你能告訴我們連接/打開串口的代碼嗎? – putu

回答

1

添加returncatchSerialPort.DataReceived事件處理程序,從while循環的情況下,exception發生退出。

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

其他線程Close端口後,讀取數據(:comPort.Read(comBuffer, 0, bytes);此行)時,會發生Exception可能。如果沒有return聲明,您將永遠不會退出while循環,GC將不會處理SerialPort。因此,當您嘗試重新打開端口時,您將失敗。

+0

非常感謝!這是我完全需要的。 – yosafat

1

爲什麼你在一個單獨的線程中調用CloseSerialOnExit?同步調用它不是更容易嗎?它真的需要很長時間嗎?

無論如何,如果你需要它,你應該確保在線程完成之前Thread對象沒有被GC'ed。你應該使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 
    } 
}