[英]How can I await that everything is done in a Rx observable sequence after unsubscribe?
[英]Learning Rx: How can I parse an observable sequence of characters into an observable sequence of strings?
这可能非常简单,但我在Rx的学习曲线底部。 我花了几个小时阅读文章,观看视频和编写代码,但我似乎对一些似乎应该非常简单的事情有一些心理障碍。
我正在从串口收集数据。 我使用Observable.FromEventPattern
捕获SerialDataReceived
事件并将其转换为可观察的字符序列。 到现在为止还挺好。
现在,我想基于分隔符来解析该字符序列。 没有涉及新行,但每个“数据包”数据都由前导码和终结符包围,两个单个字符。 为了论证,我们可以说它们是大括号{
和}
。
所以,如果我得到的字符序列j
u
n
k
{
H
e
l
l
o
}
j
u
n
k
在我的字符序列,那么我想发出任何Hello
或{Hello}
我的字符串序列。
我可能错过了一些简单的东西,但我甚至无法弄清楚如何处理这个问题。 有什么建议吗?
使用Publish
和Buffer
可以轻松完成此操作:
var source = "junk{Hello}junk{World}junk".ToObservable();
var messages = source
.Publish(o =>
{
return o.Buffer(
o.Where(c => c == '{'),
_ => o.Where(c => c == '}'));
})
.Select(buffer => new string(buffer.ToArray()));
messages.Subscribe(x => Console.WriteLine(x));
Console.ReadLine();
这个输出是:
{Hello}
{World}
我们的想法是,您可以在调用Buffer
使用以下打开和关闭选择器。 使用Publish
是为了确保所有三个Buffer
,开放选择器和结束选择器共享相同的订阅。
source: junk{Hello}junk{World}junk|
opening: ----{----------{----------|
closing: ------}|
closing: ------}|
使用“ 扫描”将您的远程接收值聚合到聚合字符串中( TAccumulate
是一个string
),并在每次获得结束括号时将该字符串重置为""
。 (我将把实现聚合功能的工作留给你)。 这会产生类似的观察
j
ju
jun
junk
junk{
junk{h
junk{hi
junk{hi}
j
ju
...
然后你可以使用Where只发出结尾的那些}
然后最后使用Select来摆脱junk
。
所以完整,应该是
IObservable<string> packetReceived =
serialPort.CharReceived
.Scan(YourAggregationFunction)
.Where(s => s.EndsWith("}"))
.Select(s => s.EverythingAfter("{"));
(我将EverythingAfter
留给你实施)。
只是注意,当您正在尝试聚合函数时,使用string
的IEnumerable
接口来测试它可能更容易,即
foreach (s in "junk{hi}hunk{ji}blah".Scan(YourAggregationFunction))
Console.WriteLine(s);
好的,这是一个完整的工作示例
static void Main(string[] args) {
var stuff = "junk{hi}junk{world}junk".ToObservable()
.Scan("", (agg, c) => agg.EndsWith("}") ? c.ToString() : agg + c)
.Where(s => s.EndsWith("}"))
.Select(s => s.Substring(s.IndexOf('{')));
foreach (var thing in stuff.ToEnumerable()) {
Console.WriteLine(thing);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.