Асинхронный последовательный порт с CancellationToken и ReadTimeout

Я пытаюсь обернуть метод чтения SerialPort в задачу, которую можно ожидать, таким образом я могу получить преимущества использования CancellationToken и тайм-аута от объекта SerialPort. Моя проблема в том, что я не могу заставить задачу выдать исключение 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 является блокирующим вызовом? Какие-либо предложения?


person Free Radical    schedule 08.12.2017    source источник


Ответы (1)


Возможны два метода.

  1. Использование ReadAsync
    Это получение объекта Stream из BaseStream объекта SreiaPort и используйте Метод Stream.ReadAsync (Byte[], Int32, Int32, CancellationToken).

    Хотя это не совсем соответствующий контент, см. здесь.
    Как отменить Stream.ReadAsync ?
    NetworkStream.ReadAsync с маркером отмены никогда отменяет

  2. Использование DataReceivedEvent и SerialDataReceivedEventHandler
    Измените так, чтобы он работал с DataReceivedEvent в качестве триггера.
    См. ответ в этой статье.
    Пример кода последовательного порта с использованием Async API в .net 4.5?

ps
Если вы хотите работать с .NET 4.0 или ниже, вам будет полезна следующая статья.
Она также будет связана с предыдущими знаниями.
Если вы должны использовать .NET System.IO.Ports.SerialPort< /a>
Построчное чтение с последовательного порта (или другой поток, ориентированный на байты)

person kunif    schedule 18.12.2017