简体   繁体   English

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

[英]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. 我试图将SerialPort的read方法包装在可以等待的任务中,这样我就可以从使用SerialPort对象获得CancellationToken和timeout的好处。 My issue is that I cannot seem to get the Task to throw a CancellationException. 我的问题是我似乎无法让Task引发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? 是否因为Port.Read方法是阻塞调用? Any suggestions? 有什么建议么?

Two methods are conceivable. 可以想到两种方法。

  1. Using ReadAsync 使用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) . 它是从SreiaPort对象的BaseStream属性获取Stream对象,并使用Stream.ReadAsync方法(Byte [],Int32,Int32,CancellationToken)

    Although it is not exactly matched content, please refer to this. 尽管内容不完全匹配,但请参考此内容。
    How to cancel Stream.ReadAsync? 如何取消Stream.ReadAsync?
    NetworkStream.ReadAsync with a cancellation token never cancels 带有取消令牌的NetworkStream.ReadAsync永远不会取消

  2. Using DataReceivedEvent and SerialDataReceivedEventHandler 使用DataReceivedEventSerialDataReceivedEventHandler
    Change so that it works with DataReceivedEvent as trigger. 进行更改,使其与DataReceivedEvent作为触发器一起使用。
    Please refer to the answer of this article. 请参考本文的答案。
    Sample serial port comms code using Async API in .net 4.5? 在.net 4.5中使用异步API的示例串行端口通信代码?

ps ps
If you want to work with .NET 4.0 or lower, the following article will be helpful. 如果要使用.NET 4.0或更低版本,则以下文章将对您有所帮助。
It will also be related knowledge to the above. 也将是与上述相关的知识。
If you must use .NET System.IO.Ports.SerialPort 如果必须使用.NET System.IO.Ports.SerialPort
Reading line-by-line from a serial port (or other byte-oriented stream) 从串行端口(或其他面向字节的流)逐行读取

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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