2

I have used serial port with its original methods like BytesToRead, Read and Write before. As it is said that these are unreliable and I had a lot busy waiting I am trying to switch to its asynchronous methods.

I need to read from serial port with 2 different time outs. First timeout is between two messages (2000 ms here) and second is between 2 chars (10 ms here). Therefore I change ReadTimeout for each ReadAsync call like this:

    public int Read(byte[] buffer, int offset, int count, bool isFirstChar)
    {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();

        try
        {
            m_serialPort.ReadTimeout = isFirstChar ? 2000 : 10;
            Task<int> task = m_serialPort.BaseStream.ReadAsync(buffer, offset, count);
            task.Wait();
            return task.Result;
        } catch (AggregateException err)
        {
            stopWatch.Stop();
            int cnt = 0;
            foreach (Exception e in err.InnerExceptions)
            {
                if (e is TimeoutException)
                {
                    Console.WriteLine(string.Format("Exception {0}: {1} Timeout: {2} ms", ++cnt, e.Message, stopWatch.ElapsedMilliseconds));
                }
            }

            return -1;
        }
    }

Output when an AggregateException occurs and no bytes are received:

Exception 1: The operation has timed-out. Timeout: 2014 ms
Exception 1: The operation has timed-out. Timeout: 2014 ms
Exception 1: The operation has timed-out. Timeout: 2014 ms
Exception 1: The operation has timed-out. Timeout: 2014 ms
Exception 1: The operation has timed-out. Timeout: 2014 ms
Exception 1: The operation has timed-out. Timeout: 3584 ms
Exception 1: The operation has timed-out. Timeout: 2014 ms
Exception 1: The operation has timed-out. Timeout: 2017 ms
Exception 1: The operation has timed-out. Timeout: 2012 ms
Exception 1: The operation has timed-out. Timeout: 2011 ms
Exception 1: The operation has timed-out. Timeout: 2016 ms
Exception 1: The operation has timed-out. Timeout: 2012 ms
Exception 1: The operation has timed-out. Timeout: 2011 ms
Exception 1: The operation has timed-out. Timeout: 2013 ms
Exception 1: The operation has timed-out. Timeout: 2013 ms

My questions are now:

  • Is this a proper way using ReadAsync method with .Wait()?
  • Is it ok to change ReadTimeout everytime before the ReadAsync call?
  • Should I use CancellationToken as parameter in ReadAsync instead, and if yes whats the best way of doing that?
user3447279
  • 89
  • 11
  • which .NET Version is this? because I cannot find SerialPort.BaseStream.ReadAsync() on MSDN and neither gives intellisense this as option ofr me – Mong Zhu Jun 10 '16 at 09:21
  • I am using 4.5! Have a look here: [link](https://msdn.microsoft.com/en-us/library/system.io.streamreader.readasync%28v=vs.110%29.aspx) – user3447279 Jun 10 '16 at 09:23
  • I am still confused, `BaseStream` is of type `Stream` and the method `ReadAsynch` belongs to `StreamReader`. I cannot reproduce your code. – Mong Zhu Jun 10 '16 at 10:36
  • No, this is not proper. Use exceptions *only* to handle exceptional conditions. Your output says that it is entirely normal to get a timeout. And your code does not treat it as exceptional either. So don't use a timeout at all. – Hans Passant Jun 13 '16 at 08:59
  • No, a timeout isnt normal, because it does normally not occur. In my example (output) connection was lost.... I also have to use a timeout to determine whether a message is valid or not. – user3447279 Jun 13 '16 at 14:01

1 Answers1

0

Question 1: you use an asynchronous method in a synchronous way. usually you would give it a callback function an wait until an event is fired and this function can be executed. Here are examples 1 & 2 for asynch await methodology

Question 2: If your circumstances require you to do so. I don't see why not.

Unfortunately I yet don't know how to answer your third question so I leave it open for now.

Mong Zhu
  • 23,309
  • 10
  • 44
  • 76