【发布时间】:2019-02-01 20:10:22
【问题描述】:
以下可观察序列将每个元素添加到 ReplaySubject,以便我可以稍后访问任何元素,甚至等待 ReplaySubject 的完成。它在达到时间跨度后完成 ReaplySubject。
ReplaySubject<string> rfidPlayer = new ReplaySubject<string>();
characteristic.WhenNotificationReceived()
.TakeUntil(Observable.Timer(TimeSpan.FromSeconds(1)))
.Subscribe(
onNext: result =>
{
string nextTag = BitConverter.ToString(result.Data);
nextTag = nextTag.Replace("-", "");
rfidPlayer.OnNext(nextTag);
},
onCompleted: () =>
{
rfidPlayer.OnCompleted();
});
我希望序列一直运行到自上次“OnNext”调用以来的给定时间,然后完成。这在各种蓝牙通信场景中非常有用,蓝牙设备会给我一个数据序列,然后在没有任何类型的完成消息或事件的情况下停止。在这些场景中,我需要启发式地确定序列何时完成,然后自己完成。因此,如果自上次蓝牙通知以来已经“太长”了,我想完成 ReplaySubject。
我可以通过创建一个计时器,在收到每个元素时重置它,然后在计时器达到“太长”时完成 ReplaySubject 来做到这一点,但我听说创建一个对象并从可观察对象中操作它订阅不是线程安全的。
关于如何在“太长”间隔后完成序列的任何建议?
据我所知,这是一个不是线程安全的版本,但应该可以按预期工作:
bool reading = true;
System.Timers.Timer timer = new System.Timers.Timer(1000);
timer.Elapsed += (sender, e) =>
{
reading = false;
};
ReplaySubject<string> rfidPlayer = new ReplaySubject<string>();
characteristic.WhenNotificationReceived()
.TakeWhile(x => reading)
.Subscribe(
onNext: result =>
{
string nextTag = BitConverter.ToString(result.Data);
nextTag = nextTag.Replace("-", "");
timer.Stop();
timer.Start();
rfidPlayer.OnNext(nextTag);
},
onCompleted: () =>
{
rfidPlayer.OnCompleted();
});
根据 Simonare 的第一个答案,这似乎令人满意:
characteristic.WhenNotificationReceived()
.Timeout(TimeSpan.FromSeconds(1))
.Subscribe(
onNext: result =>
{
string nextTag = BitConverter.ToString(result.Data);
nextTag = nextTag.Replace("-", "");
rfidPlayer.OnNext(nextTag);
},
onError: error =>
{
rfidPlayer.OnCompleted();
});
【问题讨论】:
-
请不要使用外部状态(即
bool reading = true;),也不要使用计时器。您正在使用一个非常强大的工具,不需要任何这些。当你正确使用 Rx 时,它的效果非常好。 -
也尽量不要在您的
.Subscribe中工作。试试这个:characteristic.WhenNotificationReceived().TakeUntil(Observable.Timer(TimeSpan.FromSeconds(1))).Select(result => BitConverter.ToString(result.Data).Replace("-", "")).Subscribe(rfidPlayer);. -
TakeUntil 是设置整体定时器还是间隔定时器?
-
@Enigmativity 感谢您的 cmets,我的 Rx 有很长的路要走,但在很大程度上取决于您的反馈。
-
不用担心。我添加了一个答案,我认为您可能会从中受益匪浅。它使用了两个我认为是最重要但经常未被充分利用的运算符——
Generate和Switch。如果你觉得有用,请告诉我。
标签: c# asynchronous system.reactive