sebastian
sebastian

Reputation: 1554

Problem with serial port data receive in C#

I have a problem with a C# program. Through the Serial port i Receive a large string about 110 characters. This part works ok, but when i add code to split the string up i receive an error after some rows. Here is the error I get:

**An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll

Additional information: Index and length must refer to a location within the string.**

Here is the code:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
      if (!comport.IsOpen) return;

      if (CurrentDataMode == DataMode.Text)
      {
        // Read all the data waiting in the buffer
        string data = comport.ReadExisting();

        Log(LogMsgType.Incoming, data);
        string ziua = data.Substring(0, 8);
        string ora = data.Substring(8, 8);
        string linie = data.Substring(18, 1);
        string interior = data.Substring(22, 3);
        string durata1 = data.Substring(26, 4);
        string durata2 = data.Substring(30, 8);
        string nrtel = data.Substring(38, 10);
        string tipapel = data.Substring(75, 1);
        string acct = data.Substring(76, 5);


      }
      else
      {
        int bytes = comport.BytesToRead;

        byte[] buffer = new byte[bytes];

        comport.Read(buffer, 0, bytes);

        Log(LogMsgType.Incoming, ByteArrayToHexString(buffer));
      }
    }

EDIT:

i've tested every substring and all of them are ok. the string lenght is 112. it can't be to short.

this error appears after a few lines of 112... about one and a half

Upvotes: 1

Views: 7270

Answers (6)

Hans Passant
Hans Passant

Reputation: 941218

This is typical behavior for a serial port. They are very slow. When the DataReceived event fires, you'd typically only get one or two characters. Notably is that it works well when you debug because single-stepping through the code gives the serial port lots of time to receive additional characters. But it will go Kaboom as soon as you run without a debugger because the string isn't long enough.

You'll need to modify the code by appending the string you receive to a string variable at class scope. Only parse the string after you've received all the characters you expected. You'll need some way to know that you've received the full response. Most typically serial devices will terminate the string with a special character. Often a line-feed.

If that's the case then you can make it easy by setting the SerialPort.NewLine property to that terminator and calling ReadLine() instead of ReadExisting().

Upvotes: 4

bla
bla

Reputation: 5480

Try make a length check for each variable assignment like this:

string acct = (data.length >= 81) ? data.Substring(76, 5) : string.empy;

The data.length could be shorter than the total length of your substring (76 + 5).

Upvotes: 0

Nick Martyshchenko
Nick Martyshchenko

Reputation: 4249

You don't check what you have enough data before processing. SerialPort.ReadExisting Method just

Reads all immediately available bytes, based on the encoding, in both the stream and the input buffer of the SerialPort object.

Your device maybe just don't have time to pass all data. So you need rewrite your logic to concatenate incoming data and process it after receiving enough data.

Upvotes: 2

amccormack
amccormack

Reputation: 13927

You should verify the length of your string before your start splitting it up. Put a conditional in there to handle the case where the string is less than what you expect, and then see if the errors persist.

Upvotes: 0

David Brown
David Brown

Reputation: 36239

The exception is telling you that, at some point, Substring is being given parameters that exceed the length of the string. Which likely means you aren't getting the data you are expecting from the serial port. Try inserting a breakpoint at the first call to Substring and check the contents of data to make sure the device you are reading from isn't sending some kind of error code or something other than what your code expects.

Upvotes: 0

Martin Klinke
Martin Klinke

Reputation: 7332

The length of "data" is probably too short for one of the calls to "Substring". Check the length of the string that you expect before accessing parts of it that may not exist.

Upvotes: 2

Related Questions