C# serial port integration with read timeouts issues

Lukas Blauzdys 0 Reputation points
2023-10-16T12:27:44.36+00:00

Hello I have a question what could be optimized for my code because for some reasons I need to increase read timeout values for serial port even tho in C++ the timeouts were even smaller and it worked fine. The C++ timeouts were 250ms and now they need to be 3000ms the code I am having troubles with is this:

 public virtual void SendSyncCommand(ISerialCommand queryCommand, ISerialCommand responseCommand)
    {
      _ = queryCommand ?? throw new ArgumentNullException(nameof(queryCommand), $"{nameof(queryCommand)} cannot be null!");
      _ = responseCommand ?? throw new ArgumentNullException(nameof(responseCommand), $"{nameof(responseCommand)} cannot be null!");

      try
      {
        bool success = false;
        int tryCount = 0;

        commandMutex.Wait();

        if(!IsConnected)
        {
          throw new DeviceException("Device is not connected");
        }

        while (!success)
        {
          tryCount++;

          string sentData = string.Empty;
          string receivedData = string.Empty;

          try
          {
            // send command
            Logger.Debug($"Request command: {queryCommand.GetType().Name} ({queryCommand.ToString()}).");
            Console.WriteLine(queryCommand.ToString());
            queryCommand.Execute(this, out sentData);

            // receive reply
            responseCommand.Receive(this, out receivedData);
            Logger.Debug($"Response command: {responseCommand.GetType().Name} ({receivedData})");

            success = true;
          }
          catch (Exception exception) when (!(exception is OperationCanceledException))
          {
            ClearBuffer();
            
            var logMessage = $"Error while communicating with the device: {exception.GetType().Name} (Sent data: [{ToHexString(sentData)}] <> Received data: [{ToHexString(receivedData)}]).";

            if (tryCount <= RetryCount) // equality to account for initial try
            {
              Logger.Warn(logMessage);
              Logger.Debug(exception.Message);
              Thread.Sleep(100); // wait before sending a new packet
            }
            else
            {
              Logger.Error(logMessage);
              Logger.Debug(exception.Message);
              throw;
            }
          }
        }
      }
      finally
      {
        commandMutex.Release();
      }
    }

 public virtual bool Read(byte[] buffer, int offset, int count)
    {
      if (count > bufferSize)
      {
        throw new ArgumentOutOfRangeException(nameof(count), $"Cannot read more than {bufferSize} bytes.");
      }

      try
      {
        connectionMutex.Wait();

        var stream = GetStream();

        if (stream is null)
        {
          return false;
        }

        if (this.offset < count)
        {
          var bytesRead = stream.Read(this.buffer, this.offset, count - this.offset);

          if (bytesRead == 0) // couldn't read any bytes, skip
          {
            throw new DeviceException("Could not read data from device connection stream.");
          }

          this.offset += bytesRead;
        }

        Array.Copy(this.buffer, 0, buffer, offset, count);

        var bytesToCopy = this.offset - count;
        Array.Copy(this.buffer, count, this.buffer, 0, bytesToCopy);
        this.offset = bytesToCopy;

        return true;
      }
      catch(Exception ex) when (ex is IOException || ex is TimeoutException || ex is InvalidOperationException)
      {
        throw new DeviceException("Failed to read data from device connection stream.", ex);
      }
      finally
      {
        connectionMutex.Release();
      }
    }
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,648 questions
{count} votes

1 answer

Sort by: Most helpful
  1. KOZ6.0 6,300 Reputation points
    2023-10-16T13:10:12.2066667+00:00

    SerialPort class doesn't appear in your code. :) Is this what you're talking about?

    SerialPort.ReadTimeout Property