【发布时间】:2014-05-21 13:20:11
【问题描述】:
我刚刚学习 Rx,并试图从使用 SerialPort 的 GPS 设备实现“NMEA 句子阅读器”。它是 GPS 数据这一事实对问题的重要性较低,所以让我们澄清一下 NMEA 格式由行组成,“$”符号表示新条目的开始,所以你得到的“句子”看起来类似于:
$[data for first line goes here]
$[data for second line goes here]
...
连接 SerialPort 的 DataReceived 事件非常简单:
var port = new SerialPort("COM3", 4800);
var serialPortSource = Observable.FromEventPattern<
SerialDataReceivedEventHandler,
SerialDataReceivedEventArgs>
(
handler => port.DataReceived += handler,
handler => port.DataReceived -= handler
).Select(e => port.ReadExisting());
这给出了IObservable<string>,但显然这里返回的字符串不一定与 NMEA 句子对齐。例如,对于上面的示例数据,可以得到这样的序列:
$[data for first line g
oes here]\r\n$[data for
second line goes here]
如何正确地将其转换为一系列实际句子?在IEnumerable的世界里,我大概会从chars的序列开始,写一个类似这样的扩展方法:
public static IEnumerable<string> ToNmeaSentence(
this IEnumerable<char> characters
)
{
var sb = new StringBuilder();
foreach (var ch in characters)
{
if (ch == '$' && sb.Length > 0)
{
yield return sb.ToString();
sb.Clear();
}
sb.Append(ch);
}
}
现在我想知道在 Rx 中是否有这种操作的惯用方式?
【问题讨论】:
-
没有什么比 Rx 更容易混淆的了。某个地方的某个人必须维护一个缓冲区来跟踪先前接收到的内容,然后将新接收到的数据附加到其中并实施规则,即收集了完整的响应以便对其进行处理。您的代码中都缺少这些。
-
@HansPassant 哈哈,+1 :-)。我想这就是这个问题的重点:在 Rx 中是否有一种简单的方法可以做到这一点(比如使用 IEnumerable 的简单扩展方法)?
-
话虽如此,这可以在 Rx 中轻松完成。 Enumerables 和 Observables 只是彼此的倒数。我会尽快发布答案。
-
你只是没有合适的技能来发帖
&&。别担心,随着时间的推移你会进步的。
标签: c# system.reactive