如何编写自己的串口数据Get/Request函数?
How to write your own Get / Request function with serial port data?
我有一个与串口通信的 class,我想模仿一个 Get 函数。问题是,串口输入的原始数据可能会也可能不会。它还必须进行处理和解析。比如我要获取一个Person对象,串口class就是这样做的
一种为 Person 发送请求的方法。
串口设备出现问题...它可能有响应,也可能没有。
字节通过处理和解析所有数据的事件处理程序进入,最终是一个 Person 对象。
我想将所有这些都打包成一个 "GetPerson" 函数,但我很难连接 1 和 3 中的步骤。第 3 步是一个始终 运行 的函数,并且更多通用解析器。
有人可以帮我 design/structure 这个吗?
编辑:我也试过使用 class 变量并通过 while 语句进行检查,如下所示,但无论出于何种原因,它都不会在 while 语句期间检查变量:
private Person person;
public Person GetPerson()
{
...
while (person == null) {}
return person;
}
据我了解你需要转换EAP to TAP. In other words to wait for some data receiving event in async\await manner. You can use TaskComplettionSource<>
for that. Based on 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。
希望对您有所帮助。
我有一个与串口通信的 class,我想模仿一个 Get 函数。问题是,串口输入的原始数据可能会也可能不会。它还必须进行处理和解析。比如我要获取一个Person对象,串口class就是这样做的
一种为 Person 发送请求的方法。
串口设备出现问题...它可能有响应,也可能没有。
字节通过处理和解析所有数据的事件处理程序进入,最终是一个 Person 对象。
我想将所有这些都打包成一个 "GetPerson" 函数,但我很难连接 1 和 3 中的步骤。第 3 步是一个始终 运行 的函数,并且更多通用解析器。
有人可以帮我 design/structure 这个吗?
编辑:我也试过使用 class 变量并通过 while 语句进行检查,如下所示,但无论出于何种原因,它都不会在 while 语句期间检查变量:
private Person person;
public Person GetPerson()
{
...
while (person == null) {}
return person;
}
据我了解你需要转换EAP to TAP. In other words to wait for some data receiving event in async\await manner. You can use TaskComplettionSource<>
for that. Based on 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。
希望对您有所帮助。