0

I have a race condition or something like it. I mean if I toggle a breakpoint before reading from COM, everything is good. But when i'm toggling it off, it freezes. writing:

    public void Send(ComMessage message)
    {
        byte[] bytes = message.Serialise();
        if (!_outputPort.IsOpen)
            _outputPort.Open();
        try
        {
            byte[] size = BitConverter.GetBytes(bytes.Length);
            _outputPort.Write(size, 0, size.Length);
            _outputPort.Write(bytes, 0, bytes.Length);
        }
        finally
        {
            if (_outputPort != _inputPort)
                _outputPort.Close();
        }
    }

reading

    private void InputPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
    {
        var port = (SerialPort) sender;

        byte[] sizeBuffer = new byte[sizeof(long)];
        port.Read(sizeBuffer, 0, sizeBuffer.Length);
        int length = BitConverter.ToInt32(sizeBuffer, 0);
        byte[] buffer = new byte[length];

        int i = 0;
        while (i < length)
        {
            int readed = port.Read(buffer, i, length - i);
            i += readed;
        }


        var message = ComMessage.Deserialize(buffer);
        MessageReceived(this, message);
    }

for example, message has 625 bytes length. If I toggle a breakpoint, port.BytesToRead is equal 625, but if I disable it, byte count is 621.

Strange, but it works for a little amount of bytes (for short messages), but doesn't for long.

Please, advice.

5
  • Read does not guarantee you read sizeBuffer.Length bytes. You need to get the int returned from from Read and use that. You are not guaranteed what was sent on one side will be received as one message on the other side. Commented Oct 27, 2014 at 18:27
  • Your Send() method is badly broken, closing the port discards the content of the transmit buffer. It works when you debug because you give the driver enough time to empty the buffer before you close the port. There's more trouble with Close(), read the MSDN article. Boilerplate is to only ever call Open() at program initialization and not Close() until it ends. Commented Oct 27, 2014 at 18:28
  • @ScottChamberlain I edited, but this version doesn't work properly too Commented Oct 27, 2014 at 18:28
  • @HansPassant thanks, I'l try it. Because I thinked I should interact with it like with db connection - open and close only when transmitting the data Commented Oct 27, 2014 at 18:29
  • 1
    For your updated version you still never check the first Read to see how many bytes it read. It may have read less than sizeof(long) bytes in. Also you are making a buffer of size long but long is Int64, you are calling ToInt32. You should be either doing sizeof(int) or even better to make it more obvious sizeof(Int32) Commented Oct 27, 2014 at 18:29

1 Answer 1

1

message has 625 bytes length. If I toggle a breakpoint, port.BytesToRead is equal 625, but if I disable it, byte count is 621.

You never check the first Read to see how many bytes it read. It may have read less than sizeof(long) bytes in. However, that is not the source of your problem, your main problem is you are making a buffer of size long but long is Int64, you are calling ToInt32 (and writing a Int32 in your sender).

The reason your byte count is 261 instead of 265 is because the first 4 bytes of your message is sitting in sizeBuffer[4] through sizeBuffer[7] which you never processed.

To fix this you should be either doing sizeof(int) or even better to make it more obvious that the buffer is for the ToInt32 call, use sizeof(Int32)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.