从 .NET 4.8 到 .NET 6 - .NET 8 的串行端口迁移

问题描述 投票:0回答:1

我想从.NET 4.8迁移到.NET 8,在以前版本的.NET中,我们可以通过创建

SerialPort
对象并为其分配读取事件来获取响应来使用串行端口。

我想使用

ReadAsync
BaseStream
方法,但是方法卡住了,没有反应。

样品:

    using System.IO.Ports;
    using System.Text;
    
    while (true)
    { 
        Console.Write("Serial port number : ");
        var port = Console.ReadLine();
        
        Console.Write("Serial baudrate : ");
        var baudrate = Console.ReadLine();
    
        SerialPort serial_port = new SerialPort()
        {
            PortName = $"COM{port}",
            BaudRate = int.Parse(baudrate),
            Parity = Parity.None,
            StopBits = StopBits.One,
            DataBits = 8
        };
    
        try
        {
            serial_port.Open();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
    
            Console.WriteLine("Do you want to exit (Y/N)?");
            var response = Console.ReadLine();
            if (response.Equals("Y", StringComparison.OrdinalIgnoreCase))
                return;
            else
                continue;
        }
    
        string response = "";
    
        while (true)
        {
            Console.Write("Send char to Serial : ");
            var command = Console.ReadLine();
            if (command.Equals("exit",StringComparison.InvariantCultureIgnoreCase))
                break;
            
            response = await ReadExists(serial_port.BaseStream).ConfigureAwait(false);
            Console.WriteLine($"Read Exist chars = {response}");
            
            await serial_port.BaseStream.WriteAsync(Encoding.ASCII.GetBytes(command));
            response = await ReadExists(serial_port.BaseStream).ConfigureAwait(false);
            Console.WriteLine($"Read chars exact after write = {response}");
            
            Thread.Sleep(50);
    
            response = await ReadExists(serial_port.BaseStream).ConfigureAwait(false);
            Console.WriteLine($"Read chars exact after write = {response}");
        }
        serial_port.Close();
    }
    
    async Task<string> ReadExists(Stream sr)
    {
        byte[] buffer = new byte[100];
        await sr.ReadAsync(buffer).ConfigureAwait(false);
        return Encoding.ASCII.GetString(buffer.ToArray());
    }

代码卡在这里:

   async Task<string> ReadExists(Stream sr)
    {
        byte[] buffer = new byte[100];
  -->   await sr.ReadAsync(buffer).ConfigureAwait(false);
        return Encoding.ASCII.GetString(buffer.ToArray());
    }

任何人都可以建议在 .NET 8 中使用具有异步兼容性的串行端口的最佳模式吗?

回答

我得到答案了:

  1. 如果将空的
    Array
    发送到
    WriteAsync
    方法,线程就会卡住。
  2. 对于发送
    Array
    SerialPort
    ,首先我们最多得到计数 bytes ,我们可以使用
    BytesToRead
    方法读取,然后调用
    BaseStream.ReadAsync
    方法。

正确代码:

using System.IO.Ports;
using System.Text;

while (true)
{
    Console.Write("Serial port number : ");
    var port = Console.ReadLine();

    Console.Write("Serial baudrate : ");
    var baudrate = Console.ReadLine();

    SerialPort serial_port = new SerialPort()
    {
        PortName = $"COM{port}",
        BaudRate = int.Parse(baudrate),
        Parity = Parity.None,
        StopBits = StopBits.One,
        DataBits = 8
    };

    try
    {
        serial_port.Open();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);

        Console.WriteLine("Do you want to exit (Y/N)?");
        var answer = Console.ReadLine();
        if (answer.Equals("Y", StringComparison.OrdinalIgnoreCase))
            return;
        else
            continue;
    }

    string response = "";

    while (true)
    {
        Console.Write("Send char to Serial : ");
        var command = Console.ReadLine();
        if (command.Equals("exit", StringComparison.InvariantCultureIgnoreCase))
            break;

        response = await ReadExistsStream(serial_port).ConfigureAwait(false);
        Console.WriteLine($"Read Exist chars = {response}");

        await serial_port.BaseStream.WriteAsync(Encoding.ASCII.GetBytes(command)).ConfigureAwait(false);
        response = await ReadExistsStream(serial_port).ConfigureAwait(false);
        Console.WriteLine($"Read chars exact after write = {response}");

        Thread.Sleep(50);

        response = await ReadExistsStream(serial_port).ConfigureAwait(false);
        Console.WriteLine($"Read chars exact after write = {response}");
    }
    serial_port.Close();
}

static async Task<string> ReadExistsStream(SerialPort sp)
{
    int lenght = sp.BytesToRead;
    if (lenght == 0)
        return "";
    byte[] buffer = new byte[lenght];
    await sp.BaseStream.ReadAsync(buffer).ConfigureAwait(false);
    return Encoding.ASCII.GetString(buffer.ToArray());
}

总结

在 NET Core 中与

SerialPort
沟通的最佳方式是:

使用

BaseStream
SerialPort
并调用
ReadAsync
WriteAsync
,如上例所示。 我为
SerialPort
做了扩展,你可以看到代码并使用来自

GitHub 源代码 NuGet 包

c# async-await serial-port .net-6.0 .net-8.0
1个回答
0
投票

回答

  1. 如果将空的
    Array
    发送到
    WriteAsync
    方法,线程就会卡住。
  2. 对于发送
    Array
    SerialPort
    ,首先我们最多得到计数 bytes ,我们可以使用
    BytesToRead
    方法读取,然后调用
    BaseStream.ReadAsync
    方法。

正确代码

using System.IO.Ports;
using System.Text;

while (true)
{
    Console.Write("Serial port number : ");
    var port = Console.ReadLine();

    Console.Write("Serial baudrate : ");
    var baudrate = Console.ReadLine();

    SerialPort serial_port = new SerialPort()
    {
        PortName = $"COM{port}",
        BaudRate = int.Parse(baudrate),
        Parity = Parity.None,
        StopBits = StopBits.One,
        DataBits = 8
    };

    try
    {
        serial_port.Open();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);

        Console.WriteLine("Do you want to exit (Y/N)?");
        var answer = Console.ReadLine();
        if (answer.Equals("Y", StringComparison.OrdinalIgnoreCase))
            return;
        else
            continue;
    }

    string response = "";

    while (true)
    {
        Console.Write("Send char to Serial : ");
        var command = Console.ReadLine();
        if (command.Equals("exit", StringComparison.InvariantCultureIgnoreCase))
            break;

        response = await ReadExistsStream(serial_port).ConfigureAwait(false);
        Console.WriteLine($"Read Exist chars = {response}");

        await serial_port.BaseStream.WriteAsync(Encoding.ASCII.GetBytes(command)).ConfigureAwait(false);
        response = await ReadExistsStream(serial_port).ConfigureAwait(false);
        Console.WriteLine($"Read chars exact after write = {response}");

        Thread.Sleep(50);

        response = await ReadExistsStream(serial_port).ConfigureAwait(false);
        Console.WriteLine($"Read chars exact after write = {response}");
    }
    serial_port.Close();
}

static async Task<string> ReadExistsStream(SerialPort sp)
{
    int lenght = sp.BytesToRead;
    if (lenght == 0)
        return "";
    byte[] buffer = new byte[lenght];
    await sp.BaseStream.ReadAsync(buffer).ConfigureAwait(false);
    return Encoding.ASCII.GetString(buffer.ToArray());
}

总结

在 NET Core 中与

SerialPort
沟通的最佳方式是:

使用

BaseStream
SerialPort
并调用
ReadAsync
WriteAsync
,如上例所示。 我为
SerialPort
做了扩展,你可以看到代码并使用来自

GitHub 源代码 NuGet 包

© www.soinside.com 2019 - 2024. All rights reserved.