简体   繁体   中英

Async Serial Port with CancellationToken and ReadTimeout

I'm trying to wrap the SerialPort's read method in a task that can be awaited, that way I can get the benefits of using a CancellationToken and the timeout from the SerialPort object. My issue is that I cannot seem to get the Task to throw a CancellationException. Here's my code...

    static CancellationTokenSource Source = new CancellationTokenSource();

    static void Main(string[] args)
    {
        TestAsyncWrapperToken();
        Console.WriteLine("Press any key to cancel");
        Console.ReadKey(true);
        Source.Cancel();
        Console.WriteLine("Source.Cancel called");
        Console.ReadLine();
    }

    static async void TestAsyncWrapperToken()
    {
        try
        {
            using (var Port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One))
            {
                Port.Open();
                var Buffer = new byte[1];
                await Task.Factory.StartNew(() =>
                {
                    Console.WriteLine("Starting Read");
                    Port.ReadTimeout = 5000;
                    Port.Read(Buffer, 0, Buffer.Length);                        
                }, Source.Token);
            }
        }
        catch (TaskCanceledException)
        {
            Console.WriteLine("Task Cancelled");
        }
        catch (TimeoutException)
        {
            Console.WriteLine("Timeout on Port");
        }
        catch (Exception Exc)
        {
            Console.WriteLine("Exception encountered {0}", Exc);
        }
    }

Is it because the Port.Read method is a blocking call? Any suggestions?

Two methods are conceivable.

  1. Using ReadAsync
    It is to get the Stream object from the BaseStream property of the SreiaPort object and use the Stream.ReadAsync Method (Byte[], Int32, Int32, CancellationToken) .

    Although it is not exactly matched content, please refer to this.
    How to cancel Stream.ReadAsync?
    NetworkStream.ReadAsync with a cancellation token never cancels

  2. Using DataReceivedEvent and SerialDataReceivedEventHandler
    Change so that it works with DataReceivedEvent as trigger.
    Please refer to the answer of this article.
    Sample serial port comms code using Async API in .net 4.5?

ps
If you want to work with .NET 4.0 or lower, the following article will be helpful.
It will also be related knowledge to the above.
If you must use .NET System.IO.Ports.SerialPort
Reading line-by-line from a serial port (or other byte-oriented stream)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM