如何用串口数据编写自己的Get / Request函数?

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

我有一个与串口通信的类,我想模仿Get函数。问题是,串口输入原始数据,可能会也可能不会。它还必须进行处理和解析。例如,如果我想获取Person对象,则串行端口类执行此操作。

  1. 发送Person请求的方法。
  2. 串行设备上发生了某些事情......它可能会响应,但可能不会。
  3. 字节通过事件处理程序进入,该事件处理程序处理和解析所有数据,最终是Person对象。

我想把它全部包装成一个“GetPerson”函数,但是我在连接1和3中的步骤时遇到了困难。步骤3是一个始终运行的函数,它更像是一个通用的解析器。

有人可以帮我设计/构建这个吗?

编辑:我也尝试使用类变量并通过while语句检查如下所示,但它不会在while语句中检查变量,无论出于何种原因:

private Person person;

public Person GetPerson()
{
   ...
   while (person == null) {}
   return person;
}
c# callback asynccallback
1个回答
0
投票

据我所知,你需要转换EAP to TAP。换句话说,以async \ await方式等待一些数据接收事件。你可以使用TaskComplettionSource<>。基于this article,我试图想象设计合适的解决方案:

public class PersonSerialPort : IDisposable
{
    private readonly SerialPort port;

    /// <summary>
    /// Timeout in milliseconds
    /// </summary>
    private const int Timeout = 5000;

    public PersonSerialPort()
    {
        // port initializing here
        port = new SerialPort(/*your parameters here*/);
        port.Open();
    }

    public async Task<Person> GetPerson()
    {
        // set up the task completion source
        var tcs = new TaskCompletionSource<Person>();

        // handler of DataReceived event of port
        var handler = default(SerialDataReceivedEventHandler);
        handler = (sender, eventArgs) =>
        {
            try
            {
                Person result = new Person();

                // some logic for filling Person fields
                // or set it null or whatever you need
                // you are free to not set result and wait for next event fired too

                tcs.SetResult(result);

            }
            finally
            {
                port.DataReceived -= handler;
            }
        };
        port.DataReceived += handler;

        // send request for person
        port.Write("Give a person number 1");

        if (await Task.WhenAny(tcs.Task, Task.Delay(Timeout)) == tcs.Task)
        {
            return tcs.Task.Result;
        }
        else
        {
            port.DataReceived -= handler;
            throw new TimeoutException("Timeout has expired");
        }
    }

    public void Dispose()
    {
        port?.Dispose();
    }
}

UPD:添加了超时逻辑,另请参阅this question

希望能帮助到你。

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