具有CancellationToken和ReadTimeout的异步串行端口

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了具有CancellationToken和ReadTimeout的异步串行端口相关的知识,希望对你有一定的参考价值。

我正在尝试将SerialPort的read方法包装在一个可以等待的任务中,这样我就能从使用CancellationToken和SerialPort对象的超时中获益。我的问题是我似乎无法让Task抛出CancellationException。这是我的代码......

    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);
        }
    }

是因为Port.Read方法是阻塞调用吗?有什么建议?

答案

可以想到两种方法。

  1. 使用ReadAsync 它是从SreiaPort对象的BaseStream property获取Stream对象并使用Stream.ReadAsync Method (Byte[], Int32, Int32, CancellationToken)。 虽然内容不完全匹配,但请参阅此内容。 How to cancel Stream.ReadAsync? NetworkStream.ReadAsync with a cancellation token never cancels
  2. 使用DataReceivedEventSerialDataReceivedEventHandler 进行更改,以便将DataReceivedEvent用作触发器。 请参阅本文的答案。 Sample serial port comms code using Async API in .net 4.5?

附: 如果您想使用.NET 4.0或更低版本,以下文章将会有所帮助。 它也将与上述相关的知识。 If you must use .NET System.IO.Ports.SerialPort Reading line-by-line from a serial port (or other byte-oriented stream)

以上是关于具有CancellationToken和ReadTimeout的异步串行端口的主要内容,如果未能解决你的问题,请参考以下文章

连续 WebJobs 和 CancellationToken

如何正确重置 CancellationToken?

我应该如何使用 DataflowBlockOptions.CancellationToken?

如何取消 CancellationToken

我应该何时调用 CancellationToken.ThrowIfCancellationRequested?

CancellationToken 不适用于 WaitForConnectionAsync