title: C# serial port sometimes missing data
body: <p>Hi i have create a program in C# to receive a string of ASCII the string is an XML markup.</p>
  
  <p>The computer i receive the data from i have no control over and does not accept a response it sends out data on the COM port about every 10 mins </p>
  
  <p>The Console app i have collects and stores this data but it does not always work i would say about 50% of the time data is missing like a packet or byte was lost and the XML string wont read into XmlDocument</p>
  
  <p>I have been trying for about a week now to make this more stable but this is my first time in C# and would like some help is there anyway to improve this.</p>
  
  <p>CODE</p>
  
  <pre><code>  class SerialPortProgram : IDisposable
    {
      // Create the serial port with basic settings
      private SerialPort port = new SerialPort("COM1",
         115200, Parity.None, 8, StopBits.One);
  
      string sBuffer = null;
      string filePath1 = @"C:\Data\data1.xml";
      string filePath2 = @"C:\Data\data2.xml";
  
      [STAThread]
      static void Main(string[] args)
      {
          // Instatiate this class
          new SerialPortProgram();
  
      }
  
      private SerialPortProgram() 
      {
          Console.WriteLine("Started Data Monitoring:");
  
          //Attach a method to be called when there
          //is data waiting in the port's buffer
          port.ReadBufferSize = 20971520;
          port.ReceivedBytesThreshold = 1;
          port.DataReceived += new SerialDataReceivedEventHandler(Port_DataReceived);
  
          //Begin communications
          port.Open();
  
          //Enter an application loop to keep this thread alive
          Application.Run();
  
      }
  
      private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
      {
          //Show all the incoming data in the port's buffer
          SerialPort sp = (SerialPort)sender;
          sBuffer += sp.ReadExisting();
  
          if (sBuffer.Length &gt; 26000) // check the file size
          {
              if (sBuffer.Substring(sBuffer.Length - 6) == "&lt;/xml&gt;") // check for end of file
              {
                  Console.WriteLine("Found: Processing...");
                  //Thread.Sleep(1000);
                  ProcessXML();
                  sBuffer = null;
                  Console.WriteLine("Done!");
                  DateTime now = DateTime.Now;
                  Console.WriteLine(now);
                  Console.WriteLine("Monitoring...");
              }
              else
              {
                  Console.WriteLine("Still Receiving Data: " + sBuffer.Length);
              }
          }
          else
          {
              Console.WriteLine("Receiving Data: " + sBuffer.Length);
          }
      }
   private void ProcessXML()
      {
          XmlDocument xmlDoc = new XmlDocument();
          try
          {
              xmlDoc.LoadXml("&lt;wrapper&gt;" + sBuffer + "&lt;/wrapper&gt;");
              int index = 0;
              XmlNodeList xnl = xmlDoc.SelectNodes("wrapper/xml");
              foreach (XmlNode node in xnl)
              {
                  // Console.WriteLine(index.ToString());
                  if (index == 0)// xml file 1
                  {
                      using (XmlReader r = new XmlNodeReader(node))
                      {
                          DataSet ds = new DataSet();
                          ds.ReadXml(r);
                          ds.WriteXml(filePath1);
                          Console.WriteLine("NEW Data1");
                          ds.Dispose();
                          var db = new Database();
                          db.SaveMetersToDatabase(ds);
                      }
                  }
                  else if (index == 1)// xml file 2
                  {
                      using (XmlReader r1 = new XmlNodeReader(node))
                      {
                          DataSet dst = new DataSet();
                          dst.ReadXml(r1);
                          dst.WriteXml(filePath2);
                          Console.WriteLine("NEW Data2");
                          dst.Dispose();
                      }
                  }
  
                  index++;
              }
          }
          catch
          {
              Console.WriteLine("Error: in data");
              try
              {
                  string now = DateTime.Now.ToString("yyyyMMddHHmmss");
                  System.IO.File.WriteAllText(@"C:\Data\log" + now + ".xml", "&lt;wrapper&gt;" + sBuffer + "&lt;/wrapper&gt;");
              }
              catch
              {
                  Console.WriteLine("Failed to write to log");
              }
          }
      }
  
      protected virtual void Dispose(bool disposing)
      {
          if (disposing &amp;&amp; port != null)
          {
              port.Dispose();
              port = null;
          }
      }
  
      public void Dispose()
      {
          Dispose(true);
          GC.SuppressFinalize(this);
      }
  
    }
  }
  </code></pre>
  
  <p>UPDATED CODE: </p>
  
  <pre><code>  private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
      {
          //Show all the incoming data in the port's buffer
          SerialPort sp = (SerialPort)sender;
          sBuffer += sp.ReadExisting();
  
          new Thread(() =&gt;
          {
              Thread.CurrentThread.IsBackground = true;
              if (sBuffer.Length &gt; 25000) // check the file size
              {
                  if (sBuffer.Substring(sBuffer.Length - 6) == "&lt;/xml&gt;") // check for end of file
                  {
                      Console.WriteLine("Found: Processing...");
                      Task.Run(() =&gt;
                      {
                          ProcessXML();
                          sBuffer = null;
                          Console.WriteLine("Done!");
                          DateTime now = DateTime.Now;
                          Console.WriteLine(now);
                          Console.WriteLine("Monitoring...");
                      });
                  }
                  else
                  {
                      Console.WriteLine("Still Receiving Data: " + sBuffer.Length);
                  }
              }
              else
              {
                  Console.WriteLine("Receiving Data: " + sBuffer.Length);
              }
          }).Start();
      }
  </code></pre>
  
  <p>UPDATE </p>
  
  <p>still having this issue could it be possible that the sending computer sometimes does not send all the data or there is packet loss i have tried everything i have tried this new code below using Serial Port BaseStream BeginRead </p>
  
  <pre><code>  private SerialPortProgram() 
      {
          Console.WriteLine("Started Data Monitoring:");
  
          //Attach a method to be called when there
          try
          {
              Port.BaudRate = 115200;
              Port.DataBits = 8;
              Port.Parity = Parity.None;
              Port.StopBits = StopBits.One;
              Port.Handshake = Handshake.None;
              Port.DtrEnable = true;
              Port.NewLine = Environment.NewLine;
              Port.ReceivedBytesThreshold = 2048;
              Port.Open();
  
              byte[] buffer = new byte[35000];
              Action StartRead = null;
              StartRead = () =&gt; {
                  Port.BaseStream.BeginRead(buffer, 0, buffer.Length, async (IAsyncResult ar) =&gt;
                  {
                      try
                      {
                          int actualLength = Port.BaseStream.EndRead(ar);
                          byte[] received = new byte[actualLength];
                          Buffer.BlockCopy(buffer, 0, received, 0, actualLength);
                          await Task.Run(() =&gt;
                          {
                              sBuffer += Encoding.ASCII.GetString(received);
                              CheckBuffer();
                          });
                      }
                      catch (Exception exc)
                      {
                          Console.WriteLine(exc);
                      }
                      StartRead();
                  }, null);
              };
              StartRead();
  
          }
          catch (Exception ex)
          {
              Console.WriteLine("Error accessing port." + ex);
              Port.Dispose();
              Application.Exit();
          }
  
          //Enter an application loop to keep this thread alive
          Application.Run();
      }
  
      private void CheckBuffer()
      {
          if (sBuffer != null &amp;&amp; sBuffer.Length &gt; 26000) // check the file size
          {
              if (sBuffer.Substring(sBuffer.Length - 6) == "&lt;/xml&gt;") // check for end of file
              {
                  new Thread(async () =&gt;
                 {
                     Console.WriteLine("Found: Processing...");
  
                     await Task.Run(() =&gt; ProcessXML());
  
                     sBuffer = null;
                     Console.WriteLine("Done!");
                     DateTime now = DateTime.Now;
                     Console.WriteLine(now);
                     Console.WriteLine("Monitoring...");
                 }).Start();
              }
              else
              {
                  Console.WriteLine("Still Receiving Data: " + sBuffer.Length);
              }
          }
          else if (sBuffer != null &amp;&amp; sBuffer.Length &gt; 0)
          {
              Console.WriteLine("Receiving Data: " + sBuffer.Length);
          }
  
      }
  </code></pre>